/*! 
* DevExpress ChartJS
* Version: 13.2.5
* Build date: Dec 3, 2013
*
* Copyright (c) 2012 - 2013 Developer Express Inc. ALL RIGHTS RESERVED
* EULA: http://chartjs.devexpress.com/EULA
*/

"use strict";

if (!window.DevExpress) {
    /*! Module core, file devexpress.js */
    (function($, global, undefined) {
        (function checkjQueryVersion(version) {
            version = version.split(".");
            if (version[0] < 1 || version[0] === 1 && version[1] < 10)
                throw Error("Your version of jQuery is too old. Please upgrade jQuery to 1.10.0 or later.");
        })($.fn.jquery);
        var Class = function() {
                var wrapOverridden = function(baseProto, methodName, method) {
                        return function() {
                                var prevCallBase = this.callBase;
                                this.callBase = baseProto[methodName];
                                try {
                                    return method.apply(this, arguments)
                                }
                                finally {
                                    this.callBase = prevCallBase
                                }
                            }
                    };
                var clonePrototype = function(obj) {
                        var func = function(){};
                        func.prototype = obj.prototype;
                        return new func
                    };
                var classImpl = function(){};
                var redefine = function(members) {
                        var self = this;
                        if (!members)
                            return self;
                        var memberNames = $.map(members, function(_, k) {
                                return k
                            });
                        $.each(["toString", "toLocaleString", "valueOf"], function() {
                            if (members[this])
                                memberNames.push(this)
                        });
                        $.each(memberNames, function() {
                            var overridden = $.isFunction(self.prototype[this]) && $.isFunction(members[this]);
                            self.prototype[this] = overridden ? wrapOverridden(self.parent.prototype, this, members[this]) : members[this]
                        });
                        return self
                    };
                var include = function() {
                        var classObj = this;
                        $.each(arguments, function() {
                            if (this.ctor)
                                classObj._includedCtors.push(this.ctor);
                            for (var name in this) {
                                if (name === "ctor")
                                    continue;
                                if (name in classObj.prototype)
                                    throw Error("Member name collision: " + name);
                                classObj.prototype[name] = this[name]
                            }
                        });
                        return classObj
                    };
                var subclassOf = function(parentClass) {
                        if (this.parent === parentClass)
                            return true;
                        if (!this.parent || !this.parent.subclassOf)
                            return false;
                        return this.parent.subclassOf(parentClass)
                    };
                classImpl.inherit = function(members) {
                    var inheritor = function() {
                            if (!this || this.constructor !== inheritor)
                                throw Error("A class must be instantiated using the 'new' keyword");
                            var instance = this,
                                ctor = instance.ctor;
                            if (ctor)
                                ctor.apply(instance, arguments);
                            $.each(instance.constructor._includedCtors, function() {
                                this.call(instance)
                            })
                        };
                    inheritor.prototype = clonePrototype(this);
                    inheritor.inherit = this.inherit;
                    inheritor.redefine = redefine;
                    inheritor.include = include;
                    inheritor.subclassOf = subclassOf;
                    inheritor.parent = this;
                    inheritor._includedCtors = this._includedCtors ? this._includedCtors.slice(0) : [];
                    inheritor.prototype.constructor = inheritor;
                    inheritor.redefine(members);
                    return inheritor
                };
                return classImpl
            }();
        function createQueue(discardPendingTasks) {
            var _tasks = [],
                _busy = false;
            function exec() {
                while (_tasks.length) {
                    var task = _tasks.shift(),
                        result = task();
                    if (result === undefined)
                        continue;
                    if (result.then) {
                        _busy = true;
                        $.when(result).always(exec);
                        return
                    }
                    throw Error("Queued task returned unexpected result");
                }
                _busy = false
            }
            function add(task, removeTaskCallback) {
                if (!discardPendingTasks)
                    _tasks.push(task);
                else {
                    if (_tasks[0] && removeTaskCallback)
                        removeTaskCallback(_tasks[0]);
                    _tasks = [task]
                }
                if (!_busy)
                    exec()
            }
            function busy() {
                return _busy
            }
            return {
                    add: add,
                    busy: busy
                }
        }
        var parseUrl = function() {
                var a = document.createElement("a"),
                    props = ["protocol", "hostname", "port", "pathname", "search", "hash"];
                var normalizePath = function(value) {
                        if (value.charAt(0) !== "/")
                            value = "/" + value;
                        return value
                    };
                return function(url) {
                        a.href = url;
                        var result = {};
                        $.each(props, function() {
                            result[this] = a[this]
                        });
                        result.pathname = normalizePath(result.pathname);
                        return result
                    }
            }();
        global.DevExpress = global.DevExpress || {};
        var enqueueAsync = function(task) {
                var deferred = $.Deferred();
                setTimeout(function() {
                    deferred.resolve(task())
                }, 60);
                return deferred
            };
        var backButtonCallback = function() {
                var callbacks = [];
                return {
                        add: function(callback) {
                            callbacks.push(callback)
                        },
                        remove: function(callback) {
                            var indexOfCallback = $.inArray(callback, callbacks);
                            if (indexOfCallback !== -1)
                                callbacks.splice(indexOfCallback, 1)
                        },
                        fire: function() {
                            var callback = callbacks.pop(),
                                result = !!callback;
                            if (result)
                                callback();
                            return result
                        },
                        hasCallback: function() {
                            return callbacks.length > 0
                        },
                        reset: function() {
                            callbacks = []
                        }
                    }
            }();
        var overlayTargetContainer = function() {
                var defaultTargetContainer = "body";
                return function(targetContainer) {
                        if (arguments.length)
                            defaultTargetContainer = targetContainer;
                        return defaultTargetContainer
                    }
            }();
        $.extend(global.DevExpress, {
            abstract: function() {
                throw Error("Not implemented");
            },
            Class: Class,
            createQueue: createQueue,
            enqueue: createQueue().add,
            enqueueAsync: enqueueAsync,
            parseUrl: parseUrl,
            backButtonCallback: backButtonCallback,
            overlayTargetContainer: overlayTargetContainer
        })
    })(jQuery, this);
    /*! Module core, file inflector.js */
    (function($, DX, undefined) {
        var _normalize = function(text) {
                if (text === undefined || text === null)
                    return "";
                return String(text)
            };
        var _ucfirst = function(text) {
                return _normalize(text).charAt(0).toUpperCase() + text.substr(1)
            };
        var _chop = function(text) {
                return _normalize(text).replace(/([a-z\d])([A-Z])/g, "$1 $2").split(/[\s_-]+/)
            };
        var dasherize = function(text) {
                return $.map(_chop(text), function(p) {
                        return p.toLowerCase()
                    }).join("-")
            };
        var underscore = function(text) {
                return dasherize(text).replace(/-/g, "_")
            };
        var camelize = function(text, upperFirst) {
                return $.map(_chop(text), function(p, i) {
                        p = p.toLowerCase();
                        if (upperFirst || i > 0)
                            p = _ucfirst(p);
                        return p
                    }).join("")
            };
        var humanize = function(text) {
                return _ucfirst(dasherize(text).replace(/-/g, " "))
            };
        var titleize = function(text) {
                return $.map(_chop(text), function(p) {
                        return _ucfirst(p.toLowerCase())
                    }).join(" ")
            };
        DX.inflector = {
            dasherize: dasherize,
            camelize: camelize,
            humanize: humanize,
            titleize: titleize,
            underscore: underscore
        }
    })(jQuery, DevExpress);
    /*! Module core, file support.js */
    (function($, DX, window) {
        var cssPrefixes = ["", "Webkit", "Moz", "O", "ms"],
            styles = document.createElement("dx").style;
        var transitionEndEventNames = {
                WebkitTransition: 'webkitTransitionEnd',
                MozTransition: 'transitionend',
                OTransition: 'oTransitionEnd',
                msTransition: 'MsTransitionEnd',
                transition: 'transitionend'
            };
        var styleProp = function(prop) {
                prop = DX.inflector.camelize(prop, true);
                for (var i = 0, cssPrefixesCount = cssPrefixes.length; i < cssPrefixesCount; i++) {
                    var specific = cssPrefixes[i] + prop;
                    if (specific in styles)
                        return specific
                }
            };
        var supportProp = function(prop) {
                return !!styleProp(prop)
            };
        DX.support = {
            touch: "ontouchstart" in window,
            pointer: window.navigator.pointerEnabled,
            transform3d: supportProp("perspective"),
            transition: supportProp("transition"),
            transitionEndEventName: transitionEndEventNames[styleProp("transition")],
            animation: supportProp("animation"),
            winJS: "WinJS" in window,
            styleProp: styleProp,
            supportProp: supportProp,
            hasKo: !!window.ko,
            hasNg: !window.ko && !!window.angular,
            inputType: function(type) {
                if (type === "text")
                    return true;
                var input = document.createElement("input");
                try {
                    input.setAttribute("type", type);
                    input.value = "wrongValue";
                    return !input.value
                }
                catch(e) {
                    return false
                }
            }
        }
    })(jQuery, DevExpress, this);
    /*! Module core, file browser.js */
    (function($, DX, global, undefined) {
        var webkitRegExp = /(webkit)[ \/]([\w.]+)/,
            operaRegExp = /(opera)(?:.*version)?[ \/]([\w.]+)/,
            ieRegExp = /(msie) ([\w.]+)/,
            mozillaRegExp = /(mozilla)(?:.*? rv:([\w.]+))?/;
        var ua = navigator.userAgent.toLowerCase();
        var browser = function() {
                var result = {},
                    matches = webkitRegExp.exec(ua) || operaRegExp.exec(ua) || ieRegExp.exec(ua) || ua.indexOf("compatible") < 0 && mozillaRegExp.exec(ua) || [],
                    browserName = matches[1],
                    browserVersion = matches[2];
                if (browserName) {
                    result[browserName] = true;
                    result.version = browserVersion
                }
                return result
            }();
        DX.browser = browser
    })(jQuery, DevExpress, this);
    /*! Module core, file position.js */
    (function($, DX, undefined) {
        var horzRe = /left|right/,
            vertRe = /top|bottom/,
            collisionRe = /fit|flip/;
        var splitPair = function(raw) {
                switch (typeof raw) {
                    case"string":
                        return raw.split(/\s+/, 2);
                    case"object":
                        return [raw.x || raw.h, raw.y || raw.v];
                    case"number":
                        return [raw];
                    default:
                        return raw
                }
            };
        var normalizeAlign = function(raw) {
                var result = {
                        h: "center",
                        v: "center"
                    };
                var pair = splitPair(raw);
                if (pair)
                    $.each(pair, function() {
                        var w = String(this).toLowerCase();
                        if (horzRe.test(w))
                            result.h = w;
                        else if (vertRe.test(w))
                            result.v = w
                    });
                return result
            };
        var normalizeOffset = function(raw) {
                var pair = splitPair(raw),
                    h = parseInt(pair && pair[0], 10),
                    v = parseInt(pair && pair[1], 10);
                if (!isFinite(h))
                    h = 0;
                if (!isFinite(v))
                    v = h;
                return {
                        h: h,
                        v: v
                    }
            };
        var normalizeCollision = function(raw) {
                var pair = splitPair(raw),
                    h = String(pair && pair[0]).toLowerCase(),
                    v = String(pair && pair[1]).toLowerCase();
                if (!collisionRe.test(h))
                    h = "none";
                if (!collisionRe.test(v))
                    v = h;
                return {
                        h: h,
                        v: v
                    }
            };
        var getAlignFactor = function(align) {
                switch (align) {
                    case"center":
                        return 0.5;
                    case"right":
                    case"bottom":
                        return 1;
                    default:
                        return 0
                }
            };
        var inverseAlign = function(align) {
                switch (align) {
                    case"left":
                        return "right";
                    case"right":
                        return "left";
                    case"top":
                        return "bottom";
                    case"bottom":
                        return "top";
                    default:
                        return align
                }
            };
        var initMyLocation = function(data) {
                data.myLocation = data.atLocation + getAlignFactor(data.atAlign) * data.atSize - getAlignFactor(data.myAlign) * data.mySize + data.offset
            };
        var decolliders = {
                fit: function(data, bounds) {
                    var result = false;
                    if (data.myLocation > bounds.max) {
                        data.myLocation = bounds.max;
                        result = true
                    }
                    if (data.myLocation < bounds.min) {
                        data.myLocation = bounds.min;
                        result = true
                    }
                    return result
                },
                flip: function(data, bounds) {
                    if (data.myAlign === "center" && data.atAlign === "center")
                        return false;
                    if (data.myLocation < bounds.min || data.myLocation > bounds.max) {
                        var inverseData = $.extend({}, data, {
                                myAlign: inverseAlign(data.myAlign),
                                atAlign: inverseAlign(data.atAlign),
                                offset: -data.offset
                            });
                        initMyLocation(inverseData);
                        if (inverseData.myLocation >= bounds.min && inverseData.myLocation <= bounds.max || inverseData.myLocation > data.myLocation)
                            data.myLocation = inverseData.myLocation;
                        return true
                    }
                    return false
                }
            };
        var scrollbarWidth;
        var defaultPositionResult = {
                h: {
                    location: 0,
                    flip: false,
                    fit: false
                },
                v: {
                    location: 0,
                    flip: false,
                    fit: false
                }
            };
        var calculatePosition = function(what, options) {
                var $what = $(what),
                    currentOffset = $what.offset(),
                    result = $.extend(true, {}, defaultPositionResult, {
                        h: {location: currentOffset.left},
                        v: {location: currentOffset.top}
                    });
                if (!options)
                    return result;
                var my = normalizeAlign(options.my),
                    at = normalizeAlign(options.at),
                    of = options.of || window,
                    offset = normalizeOffset(options.offset),
                    collision = normalizeCollision(options.collision);
                var h = {
                        mySize: $what.outerWidth(),
                        myAlign: my.h,
                        atAlign: at.h,
                        offset: offset.h,
                        collision: collision.h
                    };
                var v = {
                        mySize: $what.outerHeight(),
                        myAlign: my.v,
                        atAlign: at.v,
                        offset: offset.v,
                        collision: collision.v
                    };
                if (of.preventDefault) {
                    h.atLocation = of.pageX;
                    v.atLocation = of.pageY;
                    h.atSize = 0;
                    v.atSize = 0
                }
                else {
                    of = $(of);
                    if ($.isWindow(of[0])) {
                        h.atLocation = of.scrollLeft();
                        v.atLocation = of.scrollTop();
                        h.atSize = of.width();
                        v.atSize = of.height()
                    }
                    else if (of[0].nodeType === 9) {
                        h.atLocation = 0;
                        v.atLocation = 0;
                        h.atSize = of.width();
                        v.atSize = of.height()
                    }
                    else {
                        var o = of.offset();
                        h.atLocation = o.left;
                        v.atLocation = o.top;
                        h.atSize = of.outerWidth();
                        v.atSize = of.outerHeight()
                    }
                }
                initMyLocation(h);
                initMyLocation(v);
                var bounds = function() {
                        var win = $(window),
                            left = win.scrollLeft(),
                            top = win.scrollTop();
                        if (scrollbarWidth === undefined)
                            scrollbarWidth = calculateScrollbarWidth();
                        var hScrollbar = document.width > document.documentElement.clientWidth,
                            vScrollbar = document.height > document.documentElement.clientHeight,
                            hZoomLevel = DX.support.touch ? document.documentElement.clientWidth / (vScrollbar ? window.innerWidth - scrollbarWidth : window.innerWidth) : 1,
                            vZoomLevel = DX.support.touch ? document.documentElement.clientHeight / (hScrollbar ? window.innerHeight - scrollbarWidth : window.innerHeight) : 1;
                        return {
                                h: {
                                    min: left,
                                    max: left + win.width() / hZoomLevel - h.mySize
                                },
                                v: {
                                    min: top,
                                    max: top + win.height() / vZoomLevel - v.mySize
                                }
                            }
                    }();
                if (decolliders[h.collision])
                    result.h[h.collision] = decolliders[h.collision](h, bounds.h);
                if (decolliders[v.collision])
                    result.v[v.collision] = decolliders[v.collision](v, bounds.v);
                $.extend(true, result, {
                    h: {location: Math.round(h.myLocation)},
                    v: {location: Math.round(v.myLocation)}
                });
                return result
            };
        var position = function(what, options) {
                var $what = $(what);
                if (!options)
                    return $what.offset();
                var targetPosition = calculatePosition($what, options);
                $what.offset({
                    left: targetPosition.h.location,
                    top: targetPosition.v.location
                })
            };
        $.extend(DX, {
            calculatePosition: calculatePosition,
            position: position
        });
        var calculateScrollbarWidth = function() {
                var $scrollDiv = $("<div>").css({
                        width: 100,
                        height: 100,
                        overflow: "scroll",
                        position: "absolute",
                        top: -9999
                    }).appendTo($("body")),
                    result = $scrollDiv.get(0).offsetWidth - $scrollDiv.get(0).clientWidth;
                $scrollDiv.remove();
                return result
            }
    })(jQuery, DevExpress);
    /*! Module core, file action.js */
    (function($, DX, undefined) {
        var actionExecutors = {};
        var registerExecutor = function(name, executor) {
                if ($.isPlainObject(name)) {
                    $.each(name, registerExecutor);
                    return
                }
                actionExecutors[name] = executor
            };
        var unregisterExecutor = function(name) {
                var args = $.makeArray(arguments);
                $.each(args, function() {
                    delete actionExecutors[this]
                })
            };
        registerExecutor({
            func: {execute: function(e) {
                    if ($.isFunction(e.action)) {
                        e.result = e.action.apply(e.context, e.args);
                        e.handled = true
                    }
                }},
            url: {execute: function(e) {
                    if (typeof e.action === "string" && e.action.charAt(0) !== "#")
                        document.location = e.action
                }},
            hash: {execute: function(e) {
                    if (typeof e.action === "string" && e.action.charAt(0) === "#")
                        document.location.hash = e.action
                }}
        });
        var Action = DX.Class.inherit({
                ctor: function(action, config) {
                    config = config || {};
                    this._action = action || $.noop;
                    this._context = config.context || window;
                    this._beforeExecute = config.beforeExecute || $.noop;
                    this._afterExecute = config.afterExecute || $.noop;
                    this._component = config.component;
                    this._excludeValidators = config.excludeValidators
                },
                execute: function() {
                    var e = {
                            action: this._action,
                            args: Array.prototype.slice.call(arguments),
                            context: this._context,
                            component: this._component,
                            canceled: false,
                            handled: false
                        };
                    if (!this._validateAction(e))
                        return;
                    this._beforeExecute.call(this._context, e);
                    if (e.canceled)
                        return;
                    var result = this._executeAction(e);
                    this._afterExecute.call(this._context, e);
                    return result
                },
                _validateAction: function(e) {
                    var excludeValidators = this._excludeValidators;
                    $.each(actionExecutors, function(name, executor) {
                        if (excludeValidators && $.inArray(name, excludeValidators) > -1)
                            return;
                        if (executor.validate)
                            executor.validate(e);
                        if (e.canceled)
                            return false
                    });
                    return !e.canceled
                },
                _executeAction: function(e) {
                    var result;
                    $.each(actionExecutors, function(index, executor) {
                        if (executor.execute)
                            executor.execute(e);
                        if (e.handled) {
                            result = e.result;
                            return false
                        }
                    });
                    return result
                }
            });
        $.extend(DX, {
            registerActionExecutor: registerExecutor,
            unregisterActionExecutor: unregisterExecutor,
            Action: Action
        });
        DX.__internals = {actionExecutors: actionExecutors}
    })(jQuery, DevExpress);
    /*! Module core, file utils.js */
    (function($, DX, undefined) {
        var PI = Math.PI,
            LN10 = Math.LN10;
        var cos = Math.cos,
            sin = Math.sin,
            abs = Math.abs,
            log = Math.log,
            floor = Math.floor,
            ceil = Math.ceil,
            max = Math.max,
            min = Math.min,
            isNaN = window.isNaN,
            Number = window.Number,
            NaN = window.NaN;
        var dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'week', 'month', 'quarter', 'year'];
        var isDefined = function(object) {
                return object !== null && object !== undefined
            };
        var isString = function(object) {
                return $.type(object) === 'string'
            };
        var isNumber = function(object) {
                return $.isNumeric(object)
            };
        var isObject = function(object) {
                return $.type(object) === 'object'
            };
        var isArray = function(object) {
                return $.type(object) === 'array'
            };
        var isDate = function(object) {
                return $.type(object) === 'date'
            };
        var isFunction = function(object) {
                return $.type(object) === 'function'
            };
        var toMilliseconds = function(value) {
                switch (value) {
                    case'millisecond':
                        return 1;
                    case'second':
                        return toMilliseconds('millisecond') * 1000;
                    case'minute':
                        return toMilliseconds('second') * 60;
                    case'hour':
                        return toMilliseconds('minute') * 60;
                    case'day':
                        return toMilliseconds('hour') * 24;
                    case'week':
                        return toMilliseconds('day') * 7;
                    case'month':
                        return toMilliseconds('day') * 30;
                    case'quarter':
                        return toMilliseconds('month') * 3;
                    case'year':
                        return toMilliseconds('day') * 365;
                    default:
                        return 0
                }
            };
        var convertDateUnitToMilliseconds = function(dateUnit, count) {
                return toMilliseconds(dateUnit) * count
            };
        var convertMillisecondsToDateUnits = function(value) {
                var i,
                    dateUnitCount,
                    dateUnitInterval,
                    dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'month', 'year'],
                    result = {};
                for (i = dateUnitIntervals.length - 1; i >= 0; i--) {
                    dateUnitInterval = dateUnitIntervals[i];
                    dateUnitCount = Math.floor(value / toMilliseconds(dateUnitInterval));
                    if (dateUnitCount > 0) {
                        result[dateUnitInterval + 's'] = dateUnitCount;
                        value -= convertDateUnitToMilliseconds(dateUnitInterval, dateUnitCount)
                    }
                }
                return result
            };
        var convertDateTickIntervalToMilliseconds = function(tickInterval) {
                var milliseconds = 0;
                if (isObject(tickInterval))
                    $.each(tickInterval, function(key, value) {
                        milliseconds += convertDateUnitToMilliseconds(key.substr(0, key.length - 1), value)
                    });
                if (isString(tickInterval))
                    milliseconds = convertDateUnitToMilliseconds(tickInterval, 1);
                return milliseconds
            };
        var getDatesDifferences = function(date1, date2) {
                var differences,
                    counter = 0;
                differences = {
                    year: date1.getFullYear() !== date2.getFullYear(),
                    month: date1.getMonth() !== date2.getMonth(),
                    day: date1.getDate() !== date2.getDate(),
                    hour: date1.getHours() !== date2.getHours(),
                    minute: date1.getMinutes() !== date2.getMinutes(),
                    second: date1.getSeconds() !== date2.getSeconds()
                };
                $.each(differences, function(key, value) {
                    if (value)
                        counter++
                });
                differences.count = counter;
                return differences
            };
        var sameMonthAndYear = function(date1, date2) {
                return date1 && date2 && date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth()
            };
        var getFirstMonthDate = function(date) {
                return new Date(date.getFullYear(), date.getMonth(), 1)
            };
        var getFraction = function(value) {
                var valueString,
                    dotIndex;
                if (isNumber(value)) {
                    valueString = value.toString();
                    dotIndex = valueString.indexOf('.');
                    if (dotIndex >= 0)
                        if (isExponential(value))
                            return valueString.substr(dotIndex + 1, valueString.indexOf('e') - dotIndex - 1);
                        else {
                            valueString = value.toFixed(20);
                            return valueString.substr(dotIndex + 1, valueString.length - dotIndex + 1)
                        }
                }
                return ''
            };
        var getSignificantDigitPosition = function(value) {
                var fraction = getFraction(value),
                    i;
                if (fraction)
                    for (i = 0; i < fraction.length; i++)
                        if (fraction.charAt(i) !== '0')
                            return i + 1;
                return 0
            };
        var addSubValues = function(value1, value2, isSub) {
                return value1 + (isSub ? -1 : 1) * value2
            };
        var isExponential = function(value) {
                return isNumber(value) && value.toString().indexOf('e') !== -1
            };
        var addInterval = function(value, interval, isNegative) {
                var result = null,
                    intervalObject;
                if (isDate(value)) {
                    intervalObject = isString(interval) ? getDateIntervalByString(interval.toLowerCase()) : interval;
                    result = new Date(value.getTime());
                    if (intervalObject.years)
                        result.setFullYear(addSubValues(result.getFullYear(), intervalObject.years, isNegative));
                    if (intervalObject.quarters)
                        result.setMonth(addSubValues(result.getMonth(), 3 * intervalObject.quarters, isNegative));
                    if (intervalObject.months)
                        result.setMonth(addSubValues(result.getMonth(), intervalObject.months, isNegative));
                    if (intervalObject.weeks)
                        result.setDate(addSubValues(result.getDate(), 7 * intervalObject.weeks, isNegative));
                    if (intervalObject.days)
                        result.setDate(addSubValues(result.getDate(), intervalObject.days, isNegative));
                    if (intervalObject.hours)
                        result.setHours(addSubValues(result.getHours(), intervalObject.hours, isNegative));
                    if (intervalObject.minutes)
                        result.setMinutes(addSubValues(result.getMinutes(), intervalObject.minutes, isNegative));
                    if (intervalObject.seconds)
                        result.setSeconds(addSubValues(result.getSeconds(), intervalObject.seconds, isNegative));
                    if (intervalObject.milliseconds)
                        result.setMilliseconds(addSubValues(value.getMilliseconds(), intervalObject.milliseconds, isNegative))
                }
                else
                    result = addSubValues(value, interval, isNegative);
                return result
            };
        var getDateUnitInterval = function(tickInterval) {
                var maxInterval = -1,
                    i;
                if (isString(tickInterval))
                    return tickInterval;
                if (isObject(tickInterval)) {
                    $.each(tickInterval, function(key, value) {
                        for (i = 0; i < dateUnitIntervals.length; i++)
                            if (value && (key === dateUnitIntervals[i] + 's' || key === dateUnitIntervals[i]) && maxInterval < i)
                                maxInterval = i
                    });
                    return dateUnitIntervals[maxInterval]
                }
                return ''
            };
        var correctDateWithUnitBeginning = function(date, dateInterval) {
                var dayMonth,
                    firstQuarterMonth,
                    dateUnitInterval = getDateUnitInterval(dateInterval);
                switch (dateUnitInterval) {
                    case'second':
                        date.setMilliseconds(0);
                        break;
                    case'minute':
                        date.setSeconds(0, 0);
                        break;
                    case'hour':
                        date.setMinutes(0, 0, 0);
                        break;
                    case'year':
                        date.setMonth(0);
                    case'month':
                        date.setDate(1);
                    case'day':
                        date.setHours(0, 0, 0, 0);
                        break;
                    case'week':
                        dayMonth = date.getDate();
                        if (date.getDay() !== 0)
                            dayMonth += 7 - date.getDay();
                        date.setDate(dayMonth);
                        date.setHours(0, 0, 0, 0);
                        break;
                    case'quarter':
                        firstQuarterMonth = DX.formatHelper.getFirstQuarterMonth(date.getMonth());
                        if (date.getMonth() !== firstQuarterMonth)
                            date.setMonth(firstQuarterMonth);
                        date.setDate(1);
                        date.setHours(0, 0, 0, 0);
                        break
                }
            };
        var roundValue = function(value, precision) {
                if (precision > 20)
                    precision = 20;
                if (isNumber(value))
                    if (isExponential(value))
                        return Number(value.toExponential(precision));
                    else
                        return Number(value.toFixed(precision))
            };
        var getPrecision = function(value) {
                var stringFraction,
                    stringValue = value.toString(),
                    pointIndex = stringValue.indexOf('.'),
                    startIndex,
                    precision;
                if (isExponential(value)) {
                    precision = getDecimalOrder(value);
                    if (precision < 0)
                        return Math.abs(precision);
                    else
                        return 0
                }
                if (pointIndex !== -1) {
                    startIndex = pointIndex + 1;
                    stringFraction = stringValue.substring(startIndex, startIndex + 20);
                    return stringFraction.length
                }
                return 0
            };
        var applyPrecisionByMinDelta = function(min, delta, value) {
                var minPrecision = getPrecision(min),
                    deltaPrecision = getPrecision(delta);
                return roundValue(value, minPrecision < deltaPrecision ? deltaPrecision : minPrecision)
            };
        var adjustValue = function(value) {
                var fraction = getFraction(value),
                    nextValue,
                    i;
                if (fraction)
                    for (i = 1; i <= fraction.length; i++) {
                        nextValue = roundValue(value, i);
                        if (nextValue !== 0 && fraction[i - 2] && fraction[i - 1] && fraction[i - 2] === fraction[i - 1])
                            return nextValue
                    }
                return value
            };
        var getDateIntervalByString = function(intervalString) {
                var result = {};
                switch (intervalString) {
                    case'year':
                        result.years = 1;
                        break;
                    case'month':
                        result.months = 1;
                        break;
                    case'quarter':
                        result.months = 3;
                        break;
                    case'week':
                        result.days = 7;
                        break;
                    case'day':
                        result.days = 1;
                        break;
                    case'hour':
                        result.hours = 1;
                        break;
                    case'minute':
                        result.minutes = 1;
                        break;
                    case'second':
                        result.seconds = 1;
                        break;
                    case'millisecond':
                        result.milliseconds = 1;
                        break
                }
                return result
            };
        var normalizeAngle = function(angle) {
                return (angle % 360 + 360) % 360
            };
        var convertAngleToRendererSpace = function(angle) {
                return 90 - angle
            };
        var degreesToRadians = function(value) {
                return PI * value / 180
            };
        var getCosAndSin = function(angle) {
                var angleInRadians = degreesToRadians(angle);
                return {
                        cos: cos(angleInRadians),
                        sin: sin(angleInRadians)
                    }
            };
        var DECIMAL_ORDER_THRESHOLD = 1E-14;
        var getDecimalOrder = function(number) {
                var n = abs(number),
                    cn;
                if (!isNaN(n)) {
                    if (n > 0) {
                        n = log(n) / LN10;
                        cn = ceil(n);
                        return cn - n < DECIMAL_ORDER_THRESHOLD ? cn : floor(n)
                    }
                    return 0
                }
                return NaN
            };
        var getAppropriateFormat = function(start, end, count) {
                var order = max(getDecimalOrder(start), getDecimalOrder(end)),
                    precision = -getDecimalOrder(abs(end - start) / count),
                    format;
                if (!isNaN(order) && !isNaN(precision)) {
                    if (abs(order) <= 4) {
                        format = 'fixedPoint';
                        precision < 0 && (precision = 0);
                        precision > 4 && (precision = 4)
                    }
                    else {
                        format = 'exponential';
                        precision += order - 1;
                        precision > 3 && (precision = 3)
                    }
                    return {
                            format: format,
                            precision: precision
                        }
                }
                return null
            };
        var createResizeHandler = function(callback) {
                var $window = $(window),
                    timeout;
                var debug_callback = arguments[1];
                var handler = function() {
                        var width = $window.width(),
                            height = $window.height();
                        clearTimeout(timeout);
                        timeout = setTimeout(function() {
                            $window.width() === width && $window.height() === height && callback();
                            debug_callback && debug_callback()
                        }, 100)
                    };
                handler.stop = function() {
                    clearTimeout(timeout);
                    return this
                };
                return handler
            };
        var logger = function() {
                var console = window.console;
                function info(text) {
                    if (!console || !$.isFunction(console.info))
                        return;
                    console.info(text)
                }
                function warn(text) {
                    if (!console || !$.isFunction(console.warn))
                        return;
                    console.warn(text)
                }
                function error(text) {
                    if (!console || !$.isFunction(console.error))
                        return;
                    console.error(text)
                }
                return {
                        info: info,
                        warn: warn,
                        error: error
                    }
            }();
        var debug = function() {
                function assert(condition, message) {
                    if (!condition)
                        throw new Error(message);
                }
                function assertParam(parameter, message) {
                    assert(parameter !== null && parameter !== undefined, message)
                }
                return {
                        assert: assert,
                        assertParam: assertParam
                    }
            }();
        var windowResizeCallbacks = function() {
                var prevSize,
                    callbacks = $.Callbacks(),
                    jqWindow = $(window);
                var formatSize = function() {
                        return [jqWindow.width(), jqWindow.height()].join()
                    };
                var handleResize = function() {
                        var now = formatSize();
                        if (now === prevSize)
                            return;
                        prevSize = now;
                        callbacks.fire()
                    };
                jqWindow.on("resize", handleResize);
                prevSize = formatSize();
                return callbacks
            }();
        var resetActiveElement = function() {
                var android4nativeBrowser = DX.devices.real.platform === "android" && /^4\.0(\.\d)?/.test(DX.devices.real.version.join(".")) && navigator.userAgent.indexOf("Chrome") === -1;
                function androidInputBlur() {
                    var $specInput = $("<input>").addClass("dx-hidden-input").appendTo("body");
                    setTimeout(function() {
                        $specInput.focus();
                        setTimeout(function() {
                            $specInput.hide();
                            $specInput.remove()
                        }, 100)
                    }, 100)
                }
                function standardInputBlur() {
                    var activeElement = document.activeElement;
                    if (activeElement && activeElement !== document.body && activeElement.blur)
                        activeElement.blur()
                }
                if (android4nativeBrowser)
                    androidInputBlur();
                else
                    standardInputBlur()
            };
        var createMarkupFromString = function(str) {
                var tempElement = $("<div />");
                if (window.WinJS)
                    WinJS.Utilities.setInnerHTMLUnsafe(tempElement.get(0), str);
                else
                    tempElement.append(str);
                return tempElement.contents()
            };
        var getNextClipId = function() {
                var numClipRect = 1;
                return function() {
                        return 'DevExpress_' + numClipRect++
                    }
            }();
        var getNextPatternId = function() {
                var numPattern = 1;
                return function() {
                        return 'DevExpressPattern_' + numPattern++
                    }
            }();
        var extendFromObject = function(target, source, overrideExistingValues) {
                target = target || {};
                for (var prop in source)
                    if (source.hasOwnProperty(prop)) {
                        var value = source[prop];
                        if (!(prop in target) || overrideExistingValues)
                            target[prop] = value
                    }
                return target
            };
        var clone = function() {
                function Clone(){}
                return function(obj) {
                        Clone.prototype = obj;
                        return new Clone
                    }
            }();
        var executeAsync = function(action, context) {
                var deferred = $.Deferred(),
                    normalizedContext = context || this;
                setTimeout(function() {
                    var result = action.call(normalizedContext);
                    if (result && result.done && $.isFunction(result.done))
                        result.done(function() {
                            deferred.resolveWith(normalizedContext)
                        });
                    else
                        deferred.resolveWith(normalizedContext)
                }, 0);
                return deferred.promise()
            };
        var getLog = function(value, base) {
                var a;
                a = Math.log(value) / Math.log(base);
                return a
            };
        var raiseTo = function(power, base) {
                var a;
                a = Math.pow(base, power);
                return a
            };
        var stringFormat = function() {
                var s = arguments[0];
                for (var i = 0; i < arguments.length - 1; i++) {
                    var reg = new RegExp("\\{" + i + "\\}", "gm");
                    s = s.replace(reg, arguments[i + 1])
                }
                return s
            };
        var getRootOffset = function(renderer) {
                var node,
                    result = {
                        left: {},
                        top: {}
                    },
                    root = renderer.getRoot();
                if (root) {
                    node = root.element;
                    if (node.getScreenCTM) {
                        var ctm = node.getScreenCTM();
                        if (ctm) {
                            result.left = node.createSVGPoint().matrixTransform(ctm).x + (document.body.scrollLeft || document.documentElement.scrollLeft);
                            result.top = node.createSVGPoint().matrixTransform(ctm).y + (document.body.scrollTop || document.documentElement.scrollTop)
                        }
                        else {
                            result.left = document.body.scrollLeft || document.documentElement.scrollLeft;
                            result.top = document.body.scrollTop || document.documentElement.scrollTop
                        }
                    }
                    else {
                        result.left = $(node).offset().left;
                        result.top = $(node).offset().top
                    }
                }
                return result
            };
        var findBestMatches = function(targetFilter, items, mapFn) {
                var bestMatches = [],
                    maxMatchCount = 0;
                $.each(items, function(index, itemSrc) {
                    var matchCount = 0,
                        item = mapFn ? mapFn(itemSrc) : itemSrc;
                    $.each(item, function(paramName) {
                        var value = targetFilter[paramName];
                        if (value !== item[paramName] && value !== undefined) {
                            matchCount = 0;
                            return false
                        }
                        else
                            matchCount++
                    });
                    if (matchCount === maxMatchCount && matchCount > 0)
                        bestMatches.push(itemSrc);
                    else if (matchCount > maxMatchCount) {
                        bestMatches.length = 0;
                        bestMatches.push(itemSrc);
                        maxMatchCount = matchCount
                    }
                });
                return bestMatches
            };
        var preg_quote = function(str) {
                return (str + "").replace(/([\+\*\?\\\.\[\^\]\$\(\)\{\}\>\<\|\=\!\:])/g, "\\$1")
            };
        var replaceAll = function(text, searchToken, replacementToken) {
                return text.replace(new RegExp("(" + preg_quote(searchToken) + ")", "gi"), replacementToken)
            };
        function icontains(elem, text) {
            return (elem.textContent || elem.innerText || $(elem).text() || "").toLowerCase().indexOf((text || "").toLowerCase()) > -1
        }
        $.expr[":"].dxicontains = $.expr.createPseudo(function(text) {
            return function(elem) {
                    return icontains(elem, text)
                }
        });
        function deepExtendArraySafe(target, changes) {
            var prevValue,
                newValue;
            for (var name in changes) {
                prevValue = target[name];
                newValue = changes[name];
                if (target === newValue)
                    continue;
                if ($.isPlainObject(newValue))
                    target[name] = deepExtendArraySafe($.isPlainObject(prevValue) ? prevValue : {}, newValue);
                else if (newValue !== undefined)
                    target[name] = newValue
            }
            return target
        }
        DX.utils = {
            dateUnitIntervals: dateUnitIntervals,
            isDefined: isDefined,
            isString: isString,
            isNumber: isNumber,
            isObject: isObject,
            isArray: isArray,
            isDate: isDate,
            isFunction: isFunction,
            getLog: getLog,
            raiseTo: raiseTo,
            normalizeAngle: normalizeAngle,
            convertAngleToRendererSpace: convertAngleToRendererSpace,
            degreesToRadians: degreesToRadians,
            getCosAndSin: getCosAndSin,
            getDecimalOrder: getDecimalOrder,
            getAppropriateFormat: getAppropriateFormat,
            getFraction: getFraction,
            adjustValue: adjustValue,
            convertMillisecondsToDateUnits: convertMillisecondsToDateUnits,
            convertDateTickIntervalToMilliseconds: convertDateTickIntervalToMilliseconds,
            convertDateUnitToMilliseconds: convertDateUnitToMilliseconds,
            getDateUnitInterval: getDateUnitInterval,
            getDatesDifferences: getDatesDifferences,
            correctDateWithUnitBeginning: correctDateWithUnitBeginning,
            roundValue: roundValue,
            isExponential: isExponential,
            applyPrecisionByMinDelta: applyPrecisionByMinDelta,
            getSignificantDigitPosition: getSignificantDigitPosition,
            addInterval: addInterval,
            getDateIntervalByString: getDateIntervalByString,
            sameMonthAndYear: sameMonthAndYear,
            getFirstMonthDate: getFirstMonthDate,
            logger: logger,
            debug: debug,
            createResizeHandler: createResizeHandler,
            windowResizeCallbacks: windowResizeCallbacks,
            resetActiveElement: resetActiveElement,
            createMarkupFromString: createMarkupFromString,
            getNextClipId: getNextClipId,
            getNextPatternId: getNextPatternId,
            extendFromObject: extendFromObject,
            clone: clone,
            executeAsync: executeAsync,
            stringFormat: stringFormat,
            getRootOffset: getRootOffset,
            findBestMatches: findBestMatches,
            replaceAll: replaceAll,
            deepExtendArraySafe: deepExtendArraySafe
        };
        DX.utils.getPrecision = getPrecision
    })(jQuery, DevExpress);
    /*! Module core, file translator.js */
    (function($, DX, undefined) {
        var support = DX.support,
            TRANSFORM_MATRIX_REGEX = /matrix(3d)?\((.+?)\)/,
            TRANSLATE_REGEX = /translate(?:3d)?\((.+?)\)/;
        var locate = function($element) {
                var result,
                    position;
                if (support.transform3d) {
                    var translate = getTranslate($element);
                    result = {
                        left: translate.x,
                        top: translate.y
                    }
                }
                else {
                    position = $element.position();
                    result = {
                        left: position.left,
                        top: position.top
                    }
                }
                return result
            };
        var move = function($element, position) {
                if (!support.transform3d) {
                    $element.css(position);
                    return
                }
                var translate = getTranslate($element),
                    left = position.left,
                    top = position.top;
                if (left !== undefined)
                    translate.x = left;
                if (top !== undefined)
                    translate.y = top;
                $element.css({
                    transform: getTranslateCss(translate),
                    transformOrigin: "0% 0%"
                })
            };
        var getTranslate = function($element) {
                var transformValue = $element.css("transform"),
                    matrix = transformValue.match(TRANSFORM_MATRIX_REGEX),
                    is3D = matrix && matrix[1];
                if (matrix) {
                    matrix = matrix[2].split(",");
                    if (is3D === "3d")
                        matrix = matrix.slice(12, 15);
                    else {
                        matrix.push(0);
                        matrix = matrix.slice(4, 7)
                    }
                }
                else
                    matrix = [0, 0, 0];
                return {
                        x: parseFloat(matrix[0]),
                        y: parseFloat(matrix[1]),
                        z: parseFloat(matrix[2])
                    }
            };
        var parseTranslate = function(translateString) {
                var result = translateString.match(TRANSLATE_REGEX);
                if (!result || !result[1])
                    return;
                result = result[1].split(",");
                result = {
                    x: parseFloat(result[0]),
                    y: parseFloat(result[1]),
                    z: parseFloat(result[2])
                };
                return result
            };
        var getTranslateCss = function(translate) {
                return "translate3d(" + (translate.x || 0) + "px, " + (translate.y || 0) + "px, " + (translate.z || 0) + "px) scale(1)"
            };
        DX.translator = {
            move: move,
            locate: locate,
            parseTranslate: parseTranslate,
            getTranslate: getTranslate,
            getTranslateCss: getTranslateCss
        }
    })(jQuery, DevExpress);
    /*! Module core, file animator.js */
    (function($, DX, undefined) {
        DX.Animator = DX.Class.inherit({
            ctor: function() {
                this._finished = true;
                this._stopped = false
            },
            start: function() {
                this._stopped = false;
                this._finished = false;
                this._stepCore()
            },
            stop: function() {
                this._stopped = true
            },
            _stepCore: function() {
                if (this._isStopped()) {
                    this._stop();
                    return
                }
                if (this._isFinished()) {
                    this._finished = true;
                    this._complete();
                    return
                }
                this._step();
                DX.requestAnimationFrame.call(window, $.proxy(this._stepCore, this))
            },
            _step: DX.abstract,
            _isFinished: $.noop,
            _stop: $.noop,
            _complete: $.noop,
            _isStopped: function() {
                return this._stopped
            },
            inProgress: function() {
                return !(this._stopped || this._finished)
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file devices.js */
    (function($, DX, undefined) {
        var knownUATable = {
                iPhone: "iPhone",
                iPhone5: "iPhone 5",
                iPad: "iPad",
                iPadMini: "iPad Mini",
                androidPhone: "Android Mobile",
                androidTablet: "Android",
                win8: "MSAppHost",
                win8Phone: "Windows Phone 8",
                msSurface: "MSIE ARM Tablet PC",
                desktop: "desktop",
                tizen: "Tizen Mobile"
            };
        var knownMajorVersion = {
                ios: [5, 6, 7],
                android: [2, 3, 4],
                win8: [8],
                tizen: [2],
                desktop: [],
                generic: []
            };
        var device;
        var current = function(deviceOrName) {
                if (deviceOrName)
                    device = getDevice(deviceOrName);
                else {
                    if (!device) {
                        var deviceOrName = undefined;
                        try {
                            deviceOrName = getDeviceOrNameFromWindowScope()
                        }
                        catch(e) {
                            deviceOrName = getDeviceNameFromSessionStorage()
                        }
                        finally {
                            if (!deviceOrName)
                                deviceOrName = getDeviceNameFromSessionStorage()
                        }
                        device = getDevice(deviceOrName)
                    }
                    return device
                }
            };
        var getDevice = function(deviceName) {
                if (deviceName === "genericPhone")
                    return {
                            deviceType: "phone",
                            platform: "generic",
                            generic: true
                        };
                if ($.isPlainObject(deviceName))
                    return fromConfig(deviceName);
                else {
                    var ua;
                    if (deviceName) {
                        ua = knownUATable[deviceName];
                        if (!ua)
                            throw Error("Unknown device");
                    }
                    else
                        ua = navigator.userAgent;
                    return fromUA(ua)
                }
            };
        var fromConfig = function(config) {
                var shortcuts = {
                        phone: config.deviceType === "phone",
                        tablet: config.deviceType === "tablet",
                        android: config.platform === "android",
                        ios: config.platform === "ios",
                        win8: config.platform === "win8",
                        tizen: config.platform === "tizen",
                        generic: config.platform === "generic"
                    };
                return $.extend({}, defaultDevice, shortcuts, config)
            };
        var fromUA = function(ua) {
                return deviceParser.ios(ua) || deviceParser.android(ua) || deviceParser.win8(ua) || deviceParser.tizen(ua) || deviceParser.desktop(ua) || genericDevice
            };
        var defaultDevice = {
                deviceType: "",
                platform: "",
                version: [],
                phone: false,
                tablet: false,
                android: false,
                ios: false,
                win8: false,
                tizen: false,
                generic: false
            };
        var genericDevice = $.extend(defaultDevice, {
                platform: "generic",
                deviceType: "phone",
                generic: true
            });
        var deviceParser = {
                ios: function(userAgent) {
                    if (!/ip(hone|od|ad)/i.test(userAgent))
                        return;
                    var isPhone = /ip(hone|od)/i.test(userAgent);
                    var matches = userAgent.match(/os (\d+)_(\d+)_?(\d+)?/i);
                    var version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10), parseInt(matches[3] || 0, 10)] : [];
                    return fromConfig({
                            deviceType: isPhone ? "phone" : "tablet",
                            platform: "ios",
                            version: version
                        })
                },
                android: function(userAgent) {
                    if (!/android|htc_|silk/i.test(userAgent))
                        return;
                    var isPhone = /mobile/i.test(userAgent);
                    var matches = userAgent.match(/android (\d+)\.(\d+)\.?(\d+)?/i);
                    var version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10), parseInt(matches[3] || 0, 10)] : [];
                    return fromConfig({
                            deviceType: isPhone ? "phone" : "tablet",
                            platform: "android",
                            version: version
                        })
                },
                win8: function(userAgent) {
                    var isPhone = /windows phone/i.test(userAgent),
                        isTablet = /msie(.*)arm(.*)tablet\spc/i.test(userAgent),
                        isDesktop = !isTablet && /msapphost/i.test(userAgent);
                    if (!(isPhone || isTablet || isDesktop))
                        return;
                    var matches = userAgent.match(/windows phone (\d+).(\d+)/i) || userAgent.match(/windows nt (\d+).(\d+)/i),
                        version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10)] : [];
                    return fromConfig({
                            deviceType: isPhone ? "phone" : isTablet ? "tablet" : "desktop",
                            platform: "win8",
                            version: version
                        })
                },
                tizen: function(userAgent) {
                    if (!/tizen/i.test(userAgent))
                        return;
                    var isPhone = /mobile/i.test(userAgent);
                    var matches = userAgent.match(/tizen (\d+)\.(\d+)/i);
                    var version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10)] : [];
                    return fromConfig({
                            deviceType: isPhone ? "phone" : "tablet",
                            platform: "tizen",
                            version: version
                        })
                },
                desktop: function(userAgent) {
                    if (!/desktop/i.test(userAgent))
                        return;
                    return fromConfig({
                            deviceType: "desktop",
                            platform: "desktop"
                        })
                }
            };
        var getDeviceOrNameFromWindowScope = function() {
                var result = undefined;
                if (window.top["dx-force-device-object"] || window.top["dx-force-device"])
                    result = window.top["dx-force-device-object"] || window.top["dx-force-device"];
                return result
            };
        var getDeviceNameFromSessionStorage = function() {
                return window.sessionStorage && (sessionStorage.getItem("dx-force-device") || sessionStorage.getItem("dx-simulator-device"))
            };
        var getDeviceMajorVersionClass = function(device) {
                var versions = knownMajorVersion[device.platform],
                    deviceVersion = device.version && device.version[0],
                    lastVersion = versions[versions.length - 1];
                if (deviceVersion) {
                    var isKnownVersion = $.inArray(parseInt(deviceVersion, 10), versions) !== -1,
                        version = isKnownVersion ? deviceVersion : lastVersion;
                    return " dx-version-major-" + version
                }
                return lastVersion ? " dx-version-major-" + lastVersion : ""
            };
        DX.devices = {
            attachCss: function(element, device) {
                var $element = $(element);
                device = device || this.current();
                var deviceTypeClass = device.deviceType ? " dx-device-" + device.deviceType : "";
                $element.addClass("dx-theme-" + device.platform).addClass("dx-theme-" + device.platform + "-typography").addClass(deviceTypeClass).addClass(getDeviceMajorVersionClass(device))
            },
            current: current,
            real: getDevice(),
            isRippleEmulator: function() {
                return !!window.tinyHippos
            }
        };
        DX.devices.__internals = {fromUA: fromUA}
    })(jQuery, DevExpress);
    /*! Module core, file fx.js */
    (function($, DX, undefined) {
        var translator = DX.translator,
            support = DX.support,
            transitionEndEventName = support.transitionEndEventName + ".dxFX";
        var CSS_TRANSITION_EASING_REGEX = /cubic-bezier\((\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\)/,
            SIMULATED_TRANSITIONEND_TIMEOUT_DATA_KEY = "dxSimulatedTransitionTimeoutKey",
            ANIM_DATA_KEY = "dxAnimData",
            TRANSFORM_PROP = "transform",
            FRAME_ANIMATION_STEP_TIME = 1000 / 60;
        var TransitionAnimationStrategy = {
                animate: function($element, config) {
                    var deferred = $.Deferred(),
                        transitionEndFired = $.Deferred(),
                        simulatedTransitionEndFired = $.Deferred();
                    $element.one(transitionEndEventName, function() {
                        transitionEndFired.reject()
                    });
                    $element.data(SIMULATED_TRANSITIONEND_TIMEOUT_DATA_KEY, setTimeout(function() {
                        simulatedTransitionEndFired.reject()
                    }, config.duration + config.delay));
                    $.when(transitionEndFired, simulatedTransitionEndFired).fail($.proxy(function() {
                        this._cleanup($element);
                        deferred.resolveWith($element, [config, $element])
                    }, this));
                    translator.getTranslate($element);
                    $element.css({
                        transitionProperty: "all",
                        transitionDelay: config.delay + "ms",
                        transitionDuration: config.duration + "ms",
                        transitionTimingFunction: config.easing
                    });
                    setProps($element, config.to);
                    if (!config.duration)
                        $element.trigger(transitionEndEventName);
                    return deferred.promise()
                },
                _cleanup: function($element) {
                    $element.css("transition", "none").off(transitionEndEventName);
                    var simulatedEndEventTimer = $element.data(SIMULATED_TRANSITIONEND_TIMEOUT_DATA_KEY);
                    clearTimeout(simulatedEndEventTimer);
                    $element.removeData(SIMULATED_TRANSITIONEND_TIMEOUT_DATA_KEY)
                },
                stop: function($element, jumpToEnd) {
                    var config = $element.data(ANIM_DATA_KEY);
                    if (!config)
                        return;
                    if (jumpToEnd)
                        $element.trigger(transitionEndEventName);
                    else {
                        $.each(config.to, function(key) {
                            $element.css(key, $element.css(key))
                        });
                        this._cleanup($element)
                    }
                }
            };
        var requestAnimationFrame = DX.requestAnimationFrame = function() {
                return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback, element) {
                        window.setTimeout(callback, FRAME_ANIMATION_STEP_TIME)
                    }
            }();
        var FrameAnimationStrategy = {
                animate: function($element, config) {
                    var deferred = $.Deferred(),
                        animationData = $element.data(ANIM_DATA_KEY),
                        self = this;
                    if (!animationData)
                        return deferred.reject().promise();
                    $.each(config.to, function(prop) {
                        if (config.from[prop] === undefined)
                            config.from[prop] = self._normalizeValue($element.css(prop))
                    });
                    if (config.to[TRANSFORM_PROP]) {
                        config.from[TRANSFORM_PROP] = self._parseTransform(config.from[TRANSFORM_PROP]);
                        config.to[TRANSFORM_PROP] = self._parseTransform(config.to[TRANSFORM_PROP])
                    }
                    animationData.frameAnimation = {
                        to: config.to,
                        from: config.from,
                        currentValue: config.from,
                        easing: convertTransitionTimingFuncToJQueryEasing(config.easing),
                        duration: config.duration,
                        startTime: (new Date).valueOf(),
                        finish: function() {
                            this.currentValue = this.to;
                            this.draw();
                            deferred.resolve()
                        },
                        draw: function() {
                            var currentValue = $.extend({}, this.currentValue);
                            if (currentValue[TRANSFORM_PROP])
                                currentValue[TRANSFORM_PROP] = $.map(currentValue[TRANSFORM_PROP], function(value, prop) {
                                    if (prop === "translate")
                                        return translator.getTranslateCss(value);
                                    else if (prop === "scale")
                                        return "scale(" + value + ")";
                                    else if (prop.substr(0, prop.length - 1) === "rotate")
                                        return prop + "(" + value + "deg)"
                                }).join(" ");
                            $element.css(currentValue)
                        }
                    };
                    if (config.delay) {
                        animationData.frameAnimation.startTime += config.delay;
                        animationData.frameAnimation.delayTimeout = setTimeout(function() {
                            self._animationStep($element)
                        }, config.delay)
                    }
                    else
                        self._animationStep($element);
                    return deferred.promise()
                },
                _parseTransform: function(transformString) {
                    var result = {};
                    $.each(transformString.match(/(\w|\d)+\([^\)]*\)\s*/g), function(i, part) {
                        var translateData = translator.parseTranslate(part),
                            scaleData = part.match(/scale\((.+?)\)/),
                            rotateData = part.match(/(rotate.)\((.+)deg\)/);
                        if (translateData)
                            result.translate = translateData;
                        if (scaleData && scaleData[1])
                            result.scale = parseFloat(scaleData[1]);
                        if (rotateData && rotateData[1])
                            result[rotateData[1]] = parseFloat(rotateData[2])
                    });
                    return result
                },
                stop: function($element, jumpToEnd) {
                    var animationData = $element.data(ANIM_DATA_KEY),
                        frameAnimation = animationData && animationData.frameAnimation;
                    if (!frameAnimation)
                        return;
                    clearTimeout(frameAnimation.delayTimeout);
                    if (jumpToEnd)
                        frameAnimation.finish()
                },
                _animationStep: function($element) {
                    var animationData = $element.data(ANIM_DATA_KEY),
                        frameAnimation = animationData && animationData.frameAnimation;
                    if (!frameAnimation)
                        return;
                    var now = (new Date).valueOf();
                    if (now >= frameAnimation.startTime + frameAnimation.duration) {
                        frameAnimation.finish();
                        return
                    }
                    frameAnimation.currentValue = this._calcStepValue(frameAnimation, now - frameAnimation.startTime);
                    frameAnimation.draw();
                    requestAnimationFrame($.proxy(function() {
                        this._animationStep($element)
                    }, this))
                },
                _calcStepValue: function(frameAnimation, currentDuration) {
                    var calcValueRecursively = function(from, to) {
                            var result = $.isArray(to) ? [] : {};
                            var calcEasedValue = function(propName) {
                                    var x = currentDuration / frameAnimation.duration,
                                        t = currentDuration,
                                        b = 1 * from[propName],
                                        c = to[propName] - from[propName],
                                        d = frameAnimation.duration;
                                    return $.easing[frameAnimation.easing](x, t, b, c, d)
                                };
                            $.each(to, function(propName, endPropValue) {
                                if (typeof endPropValue === "string" && parseFloat(endPropValue, 10) === false)
                                    return true;
                                result[propName] = typeof endPropValue === "object" ? calcValueRecursively(from[propName], endPropValue) : calcEasedValue(propName)
                            });
                            return result
                        };
                    return calcValueRecursively(frameAnimation.from, frameAnimation.to)
                },
                _normalizeValue: function(value) {
                    var numericValue = parseFloat(value, 10);
                    if (numericValue === false)
                        return value;
                    return numericValue
                }
            };
        var animationStrategies = {
                transition: support.transition ? TransitionAnimationStrategy : FrameAnimationStrategy,
                frame: FrameAnimationStrategy
            };
        var getAnimationStrategy = function(config) {
                return animationStrategies[config && config.strategy || "transition"]
            };
        var TransitionTimingFuncMap = {
                linear: "cubic-bezier(0, 0, 1, 1)",
                ease: "cubic-bezier(0.25, 0.1, 0.25, 1)",
                "ease-in": "cubic-bezier(0.42, 0, 1, 1)",
                "ease-out": "cubic-bezier(0, 0, 0.58, 1)",
                "ease-in-out": "cubic-bezier(0.42, 0, 0.58, 1)"
            };
        var convertTransitionTimingFuncToJQueryEasing = function(cssTransitionEasing) {
                cssTransitionEasing = TransitionTimingFuncMap[cssTransitionEasing] || cssTransitionEasing;
                var bezCoeffs = cssTransitionEasing.match(CSS_TRANSITION_EASING_REGEX);
                if (!bezCoeffs)
                    return "linear";
                bezCoeffs = bezCoeffs.slice(1, 5);
                $.each(bezCoeffs, function(index, value) {
                    bezCoeffs[index] = parseFloat(value)
                });
                var easingName = "cubicbezier_" + bezCoeffs.join("_").replace(/\./g, "p");
                if (!$.isFunction($.easing[easingName])) {
                    var polynomBezier = function(x1, y1, x2, y2) {
                            var Cx = 3 * x1,
                                Bx = 3 * (x2 - x1) - Cx,
                                Ax = 1 - Cx - Bx,
                                Cy = 3 * y1,
                                By = 3 * (y2 - y1) - Cy,
                                Ay = 1 - Cy - By;
                            var bezierX = function(t) {
                                    return t * (Cx + t * (Bx + t * Ax))
                                };
                            var bezierY = function(t) {
                                    return t * (Cy + t * (By + t * Ay))
                                };
                            var findXfor = function(t) {
                                    var x = t,
                                        i = 0,
                                        z;
                                    while (i < 14) {
                                        z = bezierX(x) - t;
                                        if (Math.abs(z) < 1e-3)
                                            break;
                                        x = x - z / derivativeX(x);
                                        i++
                                    }
                                    return x
                                };
                            var derivativeX = function(t) {
                                    return Cx + t * (2 * Bx + t * 3 * Ax)
                                };
                            return function(t) {
                                    return bezierY(findXfor(t))
                                }
                        };
                    $.easing[easingName] = function(x, t, b, c, d) {
                        return c * polynomBezier(bezCoeffs[0], bezCoeffs[1], bezCoeffs[2], bezCoeffs[3])(t / d) + b
                    }
                }
                return easingName
            };
        var baseConfigValidator = function(config, animationType) {
                $.each(["from", "to"], function() {
                    if (!$.isPlainObject(config[this]))
                        throw Error("Animation with the '" + animationType + "' type requires '" + this + "' configuration as an plain object.");
                })
            };
        var CustomAnimationConfigurator = {setup: function($element, config){}};
        var SlideAnimationConfigurator = {
                validateConfig: function(config) {
                    baseConfigValidator(config, "slide")
                },
                setup: function($element, config) {
                    var animStrategy = getAnimationStrategy(config);
                    if (!support.transform3d || animStrategy !== TransitionAnimationStrategy && animStrategy !== FrameAnimationStrategy)
                        return;
                    this._setupConfig($element, config.from);
                    this._setupConfig($element, config.to)
                },
                _setupConfig: function($element, config) {
                    var translate = translator.getTranslate($element),
                        left = config.left,
                        top = config.top;
                    if (left !== undefined) {
                        translate.x = left;
                        delete config.left
                    }
                    if (top !== undefined) {
                        translate.y = top;
                        delete config.top
                    }
                    config[TRANSFORM_PROP] = translator.getTranslateCss(translate)
                }
            };
        var FadeAnimationConfigurator = {setup: function($element, config) {
                    var from = config.from,
                        fromOpacity = $.isPlainObject(from) ? $element.css("opacity") : String(from),
                        toOpacity = String(config.to);
                    config.from = {opacity: fromOpacity};
                    config.to = {opacity: toOpacity}
                }};
        var PopAnimationConfigurator = {
                validateConfig: function(config) {
                    baseConfigValidator(config, "pop")
                },
                setup: function($element, config) {
                    if (!support.transform3d)
                        return;
                    var from = config.from,
                        to = config.to,
                        fromOpacity = "opacity" in from ? from.opacity : $element.css("opacity"),
                        toOpacicy = "opacity" in to ? to.opacity : 1,
                        fromScale = "scale" in from ? from.scale : 0,
                        toScale = "scale" in to ? to.scale : 1;
                    config.from = {opacity: fromOpacity};
                    config.from[TRANSFORM_PROP] = this._getCssTransform(fromScale);
                    config.to = {opacity: toOpacicy};
                    config.to[TRANSFORM_PROP] = this._getCssTransform(toScale)
                },
                _getCssTransform: function(scale) {
                    return "scale(" + scale + ")"
                }
            };
        var animationConfigurators = {
                custom: CustomAnimationConfigurator,
                slide: SlideAnimationConfigurator,
                fade: FadeAnimationConfigurator,
                pop: PopAnimationConfigurator
            };
        var getAnimationConfigurator = function(type) {
                var result = animationConfigurators[type];
                if (!result)
                    throw Error("Unknown animation type \"" + type + "\"");
                return result
            };
        var defaultConfig = {
                type: "custom",
                from: {},
                to: {},
                duration: 400,
                complete: $.noop,
                easing: "ease",
                delay: 0
            };
        var animate = function(element, config) {
                config = $.extend(true, {}, defaultConfig, config);
                var $element = $(element),
                    configurator = getAnimationConfigurator(config.type);
                if (!$element.length)
                    return $.Deferred().resolve().promise();
                if ($.isFunction(configurator.validateConfig))
                    configurator.validateConfig(config);
                configurator.setup($element, config);
                stop($element);
                setProps($element, config.from);
                return executeAnimation($element, config).done(config.complete)
            };
        var setProps = function($element, props) {
                $.each(props, function(key, value) {
                    $element.css(key, value)
                })
            };
        var executeAnimation = function($element, config) {
                var deferred = $.Deferred();
                $element.data(ANIM_DATA_KEY, config);
                if (DX.fx.off)
                    config.duration = 0;
                getAnimationStrategy(config).animate($element, config).done(function() {
                    $element.removeData(ANIM_DATA_KEY);
                    deferred.resolveWith(this, [$element, config])
                });
                return deferred.promise()
            };
        var animating = function($element) {
                return !!$element.data(ANIM_DATA_KEY)
            };
        var stop = function(element, jumpToEnd) {
                var $element = $(element);
                getAnimationStrategy($element.data(ANIM_DATA_KEY)).stop($element, jumpToEnd);
                $element.removeData(ANIM_DATA_KEY)
            };
        DX.fx = {
            off: false,
            animationTypes: animationConfigurators,
            animate: animate,
            animating: animating,
            stop: stop
        };
        DX.fx.__internals = {convertTransitionTimingFuncToJQueryEasing: convertTransitionTimingFuncToJQueryEasing}
    })(jQuery, DevExpress);
    /*! Module core, file endpointSelector.js */
    (function($, DX, undefined) {
        var location = window.location,
            DXPROXY_HOST = "dxproxy.devexpress.com:8000",
            WIN_JS = location.protocol === "ms-appx:",
            IS_DXPROXY = location.host === DXPROXY_HOST,
            IS_LOCAL = isLocalHostName(location.hostname);
        function isLocalHostName(url) {
            return /^(localhost$|127\.)/i.test(url)
        }
        var extractProxyAppId = function() {
                return location.pathname.split("/")[1]
            };
        var formatProxyUrl = function(localUrl) {
                var urlData = DX.parseUrl(localUrl);
                if (!isLocalHostName(urlData.hostname))
                    return localUrl;
                return "http://" + DXPROXY_HOST + "/" + extractProxyAppId() + "_" + urlData.port + urlData.pathname + urlData.search
            };
        var EndpointSelector = DX.EndpointSelector = function(config) {
                this.config = config
            };
        EndpointSelector.prototype = {urlFor: function(key) {
                var bag = this.config[key];
                if (!bag)
                    throw Error("Unknown endpoint key");
                if (IS_DXPROXY)
                    return formatProxyUrl(bag.local);
                if (bag.production)
                    if (WIN_JS && !Debug.debuggerEnabled || !WIN_JS && !IS_LOCAL)
                        return bag.production;
                return bag.local
            }}
    })(jQuery, DevExpress);
    /*! Module core, file formatHelper.js */
    (function($, DX, undefined) {
        var utils = DX.utils;
        DX.NumericFormat = {
            currency: 'C',
            fixedpoint: 'N',
            exponential: '',
            percent: 'P',
            decimal: 'D'
        };
        DX.LargeNumberFormatPostfixes = {
            1: 'K',
            2: 'M',
            3: 'B',
            4: 'T'
        };
        var MAX_LARGE_NUMBER_POWER = 4,
            DECIMAL_BASE = 10;
        DX.LargeNumberFormatPowers = {
            largenumber: 'auto',
            thousands: 1,
            millions: 2,
            billions: 3,
            trillions: 4
        };
        DX.DateTimeFormat = {
            longdate: 'D',
            longtime: 'T',
            monthandday: 'M',
            monthandyear: 'Y',
            quarterandyear: 'qq',
            shortdate: 'd',
            shorttime: 't',
            millisecond: 'fff',
            second: 'T',
            minute: 't',
            hour: 't',
            day: 'dd',
            week: 'dd',
            month: 'MMMM',
            quarter: 'qq',
            year: 'yyyy',
            longdatelongtime: 'D',
            shortdateshorttime: 'd'
        };
        DX.formatHelper = {
            romanDigits: ['I', 'II', 'III', 'IV'],
            _addFormatSeparator: function(format1, format2) {
                var separator = ' ';
                if (format2)
                    return format1 + separator + format2;
                return format1
            },
            _getDateTimeFormatPattern: function(dateTimeFormat) {
                return Globalize.findClosestCulture().calendar.patterns[DX.DateTimeFormat[dateTimeFormat.toLowerCase()]]
            },
            _isDateFormatContains: function(format) {
                var result = false;
                $.each(DX.DateTimeFormat, function(key, value) {
                    result = key === format.toLowerCase();
                    return !result
                });
                return result
            },
            getQuarter: function(month) {
                return Math.floor(month / 3)
            },
            getQuarterString: function(date, format) {
                var resultQuarter = '',
                    quarter = this.getQuarter(date.getMonth());
                switch (format) {
                    case'q':
                        resultQuarter = this.romanDigits[quarter];
                        break;
                    case'qq':
                        resultQuarter = 'Q' + this.romanDigits[quarter];
                        break;
                    case'Q':
                        resultQuarter = (quarter + 1).toString();
                        break;
                    case'QQ':
                        resultQuarter = 'Q' + (quarter + 1).toString();
                        break
                }
                return resultQuarter
            },
            getFirstQuarterMonth: function(month) {
                return this.getQuarter(month) * 3
            },
            _formatCustomString: function(value, format) {
                var regExp = /qq|q|QQ|Q/g,
                    quarterFormat,
                    result = '',
                    index = 0;
                while (index < format.length) {
                    quarterFormat = regExp.exec(format);
                    if (!quarterFormat || quarterFormat.index > index)
                        result += Globalize.format(value, format.substring(index, quarterFormat ? quarterFormat.index : format.length));
                    if (quarterFormat) {
                        result += this.getQuarterString(value, quarterFormat[0]);
                        index = quarterFormat.index + quarterFormat[0].length
                    }
                    else
                        index = format.length
                }
                return result
            },
            _parseNumberFormatString: function(format) {
                var formatList,
                    formatObject = {};
                if (!format || typeof format !== 'string')
                    return;
                formatList = format.toLowerCase().split(' ');
                $.each(formatList, function(index, value) {
                    if (value in DX.NumericFormat)
                        formatObject.formatType = value;
                    else if (value in DX.LargeNumberFormatPowers)
                        formatObject.power = DX.LargeNumberFormatPowers[value]
                });
                if (formatObject.power && !formatObject.formatType)
                    formatObject.formatType = 'fixedpoint';
                if (formatObject.formatType)
                    return formatObject
            },
            _calculateNumberPower: function(value, base, minPower, maxPower) {
                var number = Math.abs(value);
                var power = 0;
                if (number > 1)
                    while (number && number >= base && (maxPower === undefined || power < maxPower)) {
                        power++;
                        number = number / base
                    }
                else if (number > 0 && number < 1)
                    while (number < 1 && (minPower === undefined || power > minPower)) {
                        power--;
                        number = number * base
                    }
                return power
            },
            _getNumberByPower: function(number, power, base) {
                var result = number;
                while (power > 0) {
                    result = result / base;
                    power--
                }
                while (power < 0) {
                    result = result * base;
                    power++
                }
                return result
            },
            _formatNumber: function(value, formatObject, precision) {
                var powerPostfix;
                if (formatObject.power === 'auto')
                    formatObject.power = this._calculateNumberPower(value, 1000, 0, MAX_LARGE_NUMBER_POWER);
                if (formatObject.power)
                    value = this._getNumberByPower(value, formatObject.power, 1000);
                powerPostfix = DX.LargeNumberFormatPostfixes[formatObject.power] || '';
                return this._formatNumberCore(value, formatObject.formatType, precision) + powerPostfix
            },
            _formatNumberExponential: function(value, precision) {
                var power = this._calculateNumberPower(value, DECIMAL_BASE),
                    number = this._getNumberByPower(value, power, DECIMAL_BASE),
                    powString;
                precision = precision === undefined ? 1 : precision;
                if (number.toFixed(precision || 0) >= DECIMAL_BASE) {
                    power++;
                    number = number / DECIMAL_BASE
                }
                powString = (power >= 0 ? '+' : '') + power.toString();
                return this._formatNumberCore(number, 'fixedpoint', precision) + 'E' + powString
            },
            _formatNumberCore: function(value, format, precision) {
                if (format === 'exponential')
                    return this._formatNumberExponential(value, precision);
                else
                    return Globalize.format(value, DX.NumericFormat[format] + (utils.isNumber(precision) ? precision : 0))
            },
            _formatDate: function(date, format, formatString) {
                var resultFormat = DX.DateTimeFormat[format.toLowerCase()];
                format = format.toLowerCase();
                if (format === 'quarterandyear')
                    resultFormat = this.getQuarterString(date, resultFormat) + ' yyyy';
                if (format === 'quarter')
                    return this.getQuarterString(date, resultFormat);
                if (format === 'longdatelongtime')
                    return this._formatDate(date, 'longdate') + ' ' + this._formatDate(date, 'longtime');
                if (format === 'shortdateshorttime')
                    return this._formatDate(date, 'shortDate') + ' ' + this._formatDate(date, 'shortTime');
                return Globalize.format(date, resultFormat)
            },
            format: function(value, format, precision) {
                if (format && format.format)
                    if (format.dateType)
                        return this._formatDateEx(value, format);
                    else if (utils.isNumber(value) && isFinite(value))
                        return this._formatNumberEx(value, format);
                return this._format(value, format, precision)
            },
            _format: function(value, format, precision) {
                var numberFormatObject;
                if (!utils.isString(format) || format === '' || !utils.isNumber(value) && !utils.isDate(value))
                    return utils.isDefined(value) ? value.toString() : '';
                numberFormatObject = this._parseNumberFormatString(format);
                if (utils.isNumber(value) && numberFormatObject)
                    return this._formatNumber(value, numberFormatObject, precision);
                if (utils.isDate(value) && this._isDateFormatContains(format))
                    return this._formatDate(value, format);
                if (!numberFormatObject && !this._isDateFormatContains(format))
                    return this._formatCustomString(value, format)
            },
            _formatNumberEx: function(value, formatInfo) {
                var self = this,
                    numericFormatType = DX.NumericFormat[formatInfo.format.toLowerCase()],
                    numberFormat = Globalize.culture().numberFormat,
                    currencyFormat = formatInfo.currencyCulture && Globalize.cultures[formatInfo.currencyCulture] ? Globalize.cultures[formatInfo.currencyCulture].numberFormat.currency : numberFormat.currency,
                    percentFormat = numberFormat.percent,
                    formatSettings = self._getUnitFormatSettings(value, formatInfo),
                    unit = formatSettings.unit,
                    precision = formatSettings.precision,
                    showTrailingZeros = formatSettings.showTrailingZeros,
                    includeGroupSeparator = formatSettings.includeGroupSeparator,
                    groupSymbol = numberFormat[","],
                    floatingSymbol = numberFormat["."],
                    number,
                    isNegative,
                    pattern,
                    currentFormat,
                    regexParts = /n|\$|-|%/g,
                    result = "";
                value = self._applyUnitToValue(value, unit);
                number = Math.abs(value);
                isNegative = value < 0;
                switch (numericFormatType) {
                    case"D":
                        pattern = "n";
                        number = Math[isNegative ? "ceil" : "floor"](number);
                        if (precision > 0) {
                            var str = "" + number;
                            for (var i = str.length; i < precision; i += 1)
                                str = "0" + str;
                            number = str
                        }
                        if (isNegative)
                            number = "-" + number;
                        break;
                    case"N":
                        currentFormat = numberFormat;
                    case"C":
                        currentFormat = currentFormat || currencyFormat;
                    case"P":
                        currentFormat = currentFormat || percentFormat;
                        pattern = isNegative ? currentFormat.pattern[0] : currentFormat.pattern[1] || "n";
                        number = Globalize.format(number * (numericFormatType === "P" ? 100 : 1), "N" + precision);
                        if (!showTrailingZeros)
                            number = self._excludeTrailingZeros(number, floatingSymbol);
                        if (!includeGroupSeparator)
                            number = number.replace(new RegExp('\\' + groupSymbol, 'g'), '');
                        break;
                    default:
                        throw"Illegal numeric format: '" + numericFormatType + "'";
                }
                for (; ; ) {
                    var lastIndex = regexParts.lastIndex,
                        matches = regexParts.exec(pattern);
                    result += pattern.slice(lastIndex, matches ? matches.index : pattern.length);
                    if (matches)
                        switch (matches[0]) {
                            case"-":
                                if (/[1-9]/.test(number))
                                    result += numberFormat["-"];
                                break;
                            case"$":
                                result += currencyFormat.symbol;
                                break;
                            case"%":
                                result += percentFormat.symbol;
                                break;
                            case"n":
                                result += number + unit;
                                break
                        }
                    else
                        break
                }
                return (formatInfo.plus && value > 0 ? "+" : '') + result
            },
            _excludeTrailingZeros: function(strValue, floatingSymbol) {
                var floatingIndex = strValue.indexOf(floatingSymbol),
                    stopIndex,
                    i;
                if (floatingIndex < 0)
                    return strValue;
                stopIndex = strValue.length;
                for (i = stopIndex - 1; i >= floatingIndex && (strValue[i] === '0' || i === floatingIndex); i--)
                    stopIndex--;
                return strValue.substring(0, stopIndex)
            },
            _getUnitFormatSettings: function(value, formatInfo) {
                var unit = formatInfo.unit || '',
                    precision = formatInfo.precision || 0,
                    includeGroupSeparator = formatInfo.includeGroupSeparator || false,
                    showTrailingZeros = formatInfo.showTrailingZeros === undefined ? true : formatInfo.showTrailingZeros,
                    significantDigits = formatInfo.significantDigits || 1,
                    absValue;
                if (unit.toLowerCase() === 'auto') {
                    showTrailingZeros = false;
                    absValue = Math.abs(value);
                    if (significantDigits < 1)
                        significantDigits = 1;
                    if (absValue >= 1000000000) {
                        unit = 'B';
                        absValue /= 1000000000
                    }
                    else if (absValue >= 1000000) {
                        unit = 'M';
                        absValue /= 1000000
                    }
                    else if (absValue >= 1000) {
                        unit = 'K';
                        absValue /= 1000
                    }
                    else
                        unit = '';
                    if (absValue == 0)
                        precision = 0;
                    else if (absValue < 1) {
                        precision = significantDigits;
                        var smallValue = Math.pow(10, -significantDigits);
                        while (absValue < smallValue) {
                            smallValue /= 10;
                            precision++
                        }
                    }
                    else if (absValue >= 100)
                        precision = significantDigits - 3;
                    else if (absValue >= 10)
                        precision = significantDigits - 2;
                    else
                        precision = significantDigits - 1
                }
                if (precision < 0)
                    precision = 0;
                return {
                        unit: unit,
                        precision: precision,
                        showTrailingZeros: showTrailingZeros,
                        includeGroupSeparator: includeGroupSeparator
                    }
            },
            _applyUnitToValue: function(value, unit) {
                if (unit == 'B')
                    return value.toFixed(1) / 1000000000;
                if (unit == 'M')
                    return value / 1000000;
                if (unit == 'K')
                    return value / 1000;
                return value
            },
            _formatDateEx: function(value, formatInfo) {
                var self = this,
                    quarterPrefix = 'Q',
                    format = formatInfo.format,
                    dateType = formatInfo.dateType,
                    calendar = Globalize.culture().calendars.standard,
                    time = undefined,
                    index,
                    dateStr;
                format = format.toLowerCase();
                if (dateType !== 'num' || format === 'dayofweek')
                    switch (format) {
                        case'monthyear':
                            return self._formatDate(value, 'monthandyear');
                        case'quarteryear':
                            return self.getQuarterString(value, 'QQ') + ' ' + value.getFullYear();
                        case'daymonthyear':
                            return self._formatDate(value, dateType + 'Date');
                        case'datehour':
                            time = new Date(value.getTime());
                            time.setMinutes(0);
                            dateStr = dateType === 'timeOnly' ? '' : self._formatDate(value, dateType + 'Date');
                            return dateType === 'timeOnly' ? self._formatDate(time, 'shorttime') : dateStr + ' ' + self._formatDate(time, 'shorttime');
                        case'datehourminute':
                            dateStr = dateType === 'timeOnly' ? '' : self._formatDate(value, dateType + 'Date');
                            return dateType === 'timeOnly' ? self._formatDate(value, 'shorttime') : dateStr + ' ' + self._formatDate(value, 'shorttime');
                        case'datehourminutesecond':
                            dateStr = dateType === 'timeOnly' ? '' : self._formatDate(value, dateType + 'Date');
                            return dateType === 'timeOnly' ? self._formatDate(value, 'longtime') : dateStr + ' ' + self._formatDate(value, 'longtime');
                        case'year':
                            dateStr = value.toString();
                            return dateType === 'abbr' ? dateStr.slice(2, 4) : dateStr;
                        case'quarter':
                            return quarterPrefix + value.toString();
                        case'month':
                            index = value - 1;
                            return dateType === 'abbr' ? calendar.months.namesAbbr[index] : calendar.months.names[index];
                        case'hour':
                            if (dateType === 'long') {
                                time = new Date;
                                time.setHours(value);
                                time.setMinutes(0);
                                return self._formatDate(time, 'shorttime')
                            }
                            else
                                return value.toString();
                        case'dayofweek':
                            index = $.inArray(value, ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']);
                            if (dateType !== 'num')
                                return dateType === 'abbr' ? calendar.days.namesAbbr[index] : calendar.days.names[index];
                            else
                                return ((index - calendar.firstDay + 1 + 7) % 8).toString();
                        default:
                            return value.toString()
                    }
                else
                    return value.toString()
            },
            getTimeFormat: function(showSecond) {
                if (showSecond)
                    return this._getDateTimeFormatPattern('longtime');
                return this._getDateTimeFormatPattern('shorttime')
            },
            getDateFormatByDifferences: function(dateDifferences) {
                var resultFormat = '';
                if (dateDifferences.millisecond)
                    resultFormat = DX.DateTimeFormat.millisecond;
                if (dateDifferences.hour || dateDifferences.minute || dateDifferences.second)
                    resultFormat = this._addFormatSeparator(this.getTimeFormat(dateDifferences.second), resultFormat);
                if (dateDifferences.year && dateDifferences.month && dateDifferences.day)
                    return this._addFormatSeparator(this._getDateTimeFormatPattern('shortdate'), resultFormat);
                if (dateDifferences.year && dateDifferences.month)
                    return DX.DateTimeFormat['monthandyear'];
                if (dateDifferences.year)
                    return DX.DateTimeFormat['year'];
                if (dateDifferences.month && dateDifferences.day)
                    return this._addFormatSeparator(this._getDateTimeFormatPattern('monthandday'), resultFormat);
                if (dateDifferences.month)
                    return DX.DateTimeFormat['month'];
                if (dateDifferences.day)
                    return this._addFormatSeparator('dddd, dd', resultFormat);
                return resultFormat
            },
            getDateFormatByTicks: function(ticks) {
                var resultFormat,
                    maxDif,
                    currentDif,
                    i,
                    dateUnitInterval;
                if (ticks.length > 1) {
                    maxDif = utils.getDatesDifferences(ticks[0], ticks[1]);
                    for (i = 1; i < ticks.length - 1; i++) {
                        currentDif = utils.getDatesDifferences(ticks[i], ticks[i + 1]);
                        if (maxDif.count < currentDif.count)
                            maxDif = currentDif
                    }
                }
                else
                    maxDif = {
                        year: true,
                        month: true,
                        day: true,
                        hour: ticks[0].getHours() > 0,
                        minute: ticks[0].getMinutes() > 0,
                        second: ticks[0].getSeconds() > 0
                    };
                resultFormat = this.getDateFormatByDifferences(maxDif);
                return resultFormat
            },
            getDateFormatByTickInterval: function(startValue, endValue, tickInterval) {
                var resultFormat,
                    dateDifferences,
                    dateUnitInterval,
                    dateDifferencesConverter = {
                        quarter: 'month',
                        week: 'day'
                    },
                    correctDateDifferences = function(dateDifferences, tickInterval, value) {
                        switch (tickInterval) {
                            case'year':
                                dateDifferences.month = value;
                            case'quarter':
                            case'month':
                                dateDifferences.day = value;
                            case'week':
                            case'day':
                                dateDifferences.hour = value;
                            case'hour':
                                dateDifferences.minute = value;
                            case'minute':
                                dateDifferences.second = value;
                            case'second':
                                dateDifferences.millisecond = value
                        }
                    },
                    correctDifferencesByMaxDate = function(differences, minDate, maxDate) {
                        if (!maxDate.getMilliseconds() && maxDate.getSeconds()) {
                            if (maxDate.getSeconds() - minDate.getSeconds() === 1) {
                                differences.millisecond = true;
                                differences.second = false
                            }
                        }
                        else if (!maxDate.getSeconds() && maxDate.getMinutes()) {
                            if (maxDate.getMinutes() - minDate.getMinutes() === 1) {
                                differences.second = true;
                                differences.minute = false
                            }
                        }
                        else if (!maxDate.getMinutes() && maxDate.getHours()) {
                            if (maxDate.getHours() - minDate.getHours() === 1) {
                                differences.minute = true;
                                differences.hour = false
                            }
                        }
                        else if (!maxDate.getHours() && maxDate.getDate() > 1) {
                            if (maxDate.getDate() - minDate.getDate() === 1) {
                                differences.hour = true;
                                differences.day = false
                            }
                        }
                        else if (maxDate.getDate() === 1 && maxDate.getMonth()) {
                            if (maxDate.getMonth() - minDate.getMonth() === 1) {
                                differences.day = true;
                                differences.month = false
                            }
                        }
                        else if (!maxDate.getMonth() && maxDate.getFullYear())
                            if (maxDate.getFullYear() - minDate.getFullYear() === 1) {
                                differences.month = true;
                                differences.year = false
                            }
                    };
                tickInterval = utils.isString(tickInterval) ? tickInterval.toLowerCase() : tickInterval;
                dateDifferences = utils.getDatesDifferences(startValue, endValue);
                if (startValue !== endValue)
                    correctDifferencesByMaxDate(dateDifferences, startValue > endValue ? endValue : startValue, startValue > endValue ? startValue : endValue);
                dateUnitInterval = utils.getDateUnitInterval(dateDifferences);
                correctDateDifferences(dateDifferences, dateUnitInterval, true);
                dateUnitInterval = utils.getDateUnitInterval(tickInterval || 'second');
                correctDateDifferences(dateDifferences, dateUnitInterval, false);
                dateDifferences[dateDifferencesConverter[dateUnitInterval] || dateUnitInterval] = true;
                resultFormat = this.getDateFormatByDifferences(dateDifferences);
                return resultFormat
            }
        }
    })(jQuery, DevExpress);
    /*! Module core, file color.js */
    (function(DX, undefined) {
        var standardColorNames = {
                aliceblue: 'f0f8ff',
                antiquewhite: 'faebd7',
                aqua: '00ffff',
                aquamarine: '7fffd4',
                azure: 'f0ffff',
                beige: 'f5f5dc',
                bisque: 'ffe4c4',
                black: '000000',
                blanchedalmond: 'ffebcd',
                blue: '0000ff',
                blueviolet: '8a2be2',
                brown: 'a52a2a',
                burlywood: 'deb887',
                cadetblue: '5f9ea0',
                chartreuse: '7fff00',
                chocolate: 'd2691e',
                coral: 'ff7f50',
                cornflowerblue: '6495ed',
                cornsilk: 'fff8dc',
                crimson: 'dc143c',
                cyan: '00ffff',
                darkblue: '00008b',
                darkcyan: '008b8b',
                darkgoldenrod: 'b8860b',
                darkgray: 'a9a9a9',
                darkgreen: '006400',
                darkkhaki: 'bdb76b',
                darkmagenta: '8b008b',
                darkolivegreen: '556b2f',
                darkorange: 'ff8c00',
                darkorchid: '9932cc',
                darkred: '8b0000',
                darksalmon: 'e9967a',
                darkseagreen: '8fbc8f',
                darkslateblue: '483d8b',
                darkslategray: '2f4f4f',
                darkturquoise: '00ced1',
                darkviolet: '9400d3',
                deeppink: 'ff1493',
                deepskyblue: '00bfff',
                dimgray: '696969',
                dodgerblue: '1e90ff',
                feldspar: 'd19275',
                firebrick: 'b22222',
                floralwhite: 'fffaf0',
                forestgreen: '228b22',
                fuchsia: 'ff00ff',
                gainsboro: 'dcdcdc',
                ghostwhite: 'f8f8ff',
                gold: 'ffd700',
                goldenrod: 'daa520',
                gray: '808080',
                green: '008000',
                greenyellow: 'adff2f',
                honeydew: 'f0fff0',
                hotpink: 'ff69b4',
                indianred: 'cd5c5c',
                indigo: '4b0082',
                ivory: 'fffff0',
                khaki: 'f0e68c',
                lavender: 'e6e6fa',
                lavenderblush: 'fff0f5',
                lawngreen: '7cfc00',
                lemonchiffon: 'fffacd',
                lightblue: 'add8e6',
                lightcoral: 'f08080',
                lightcyan: 'e0ffff',
                lightgoldenrodyellow: 'fafad2',
                lightgrey: 'd3d3d3',
                lightgreen: '90ee90',
                lightpink: 'ffb6c1',
                lightsalmon: 'ffa07a',
                lightseagreen: '20b2aa',
                lightskyblue: '87cefa',
                lightslateblue: '8470ff',
                lightslategray: '778899',
                lightsteelblue: 'b0c4de',
                lightyellow: 'ffffe0',
                lime: '00ff00',
                limegreen: '32cd32',
                linen: 'faf0e6',
                magenta: 'ff00ff',
                maroon: '800000',
                mediumaquamarine: '66cdaa',
                mediumblue: '0000cd',
                mediumorchid: 'ba55d3',
                mediumpurple: '9370d8',
                mediumseagreen: '3cb371',
                mediumslateblue: '7b68ee',
                mediumspringgreen: '00fa9a',
                mediumturquoise: '48d1cc',
                mediumvioletred: 'c71585',
                midnightblue: '191970',
                mintcream: 'f5fffa',
                mistyrose: 'ffe4e1',
                moccasin: 'ffe4b5',
                navajowhite: 'ffdead',
                navy: '000080',
                oldlace: 'fdf5e6',
                olive: '808000',
                olivedrab: '6b8e23',
                orange: 'ffa500',
                orangered: 'ff4500',
                orchid: 'da70d6',
                palegoldenrod: 'eee8aa',
                palegreen: '98fb98',
                paleturquoise: 'afeeee',
                palevioletred: 'd87093',
                papayawhip: 'ffefd5',
                peachpuff: 'ffdab9',
                peru: 'cd853f',
                pink: 'ffc0cb',
                plum: 'dda0dd',
                powderblue: 'b0e0e6',
                purple: '800080',
                red: 'ff0000',
                rosybrown: 'bc8f8f',
                royalblue: '4169e1',
                saddlebrown: '8b4513',
                salmon: 'fa8072',
                sandybrown: 'f4a460',
                seagreen: '2e8b57',
                seashell: 'fff5ee',
                sienna: 'a0522d',
                silver: 'c0c0c0',
                skyblue: '87ceeb',
                slateblue: '6a5acd',
                slategray: '708090',
                snow: 'fffafa',
                springgreen: '00ff7f',
                steelblue: '4682b4',
                tan: 'd2b48c',
                teal: '008080',
                thistle: 'd8bfd8',
                tomato: 'ff6347',
                turquoise: '40e0d0',
                violet: 'ee82ee',
                violetred: 'd02090',
                wheat: 'f5deb3',
                white: 'ffffff',
                whitesmoke: 'f5f5f5',
                yellow: 'ffff00',
                yellowgreen: '9acd32'
            };
        var standardColorTypes = [{
                    re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
                    process: function(colorString) {
                        return [parseInt(colorString[1], 10), parseInt(colorString[2], 10), parseInt(colorString[3], 10)]
                    }
                }, {
                    re: /^#(\w{2})(\w{2})(\w{2})$/,
                    process: function(colorString) {
                        return [parseInt(colorString[1], 16), parseInt(colorString[2], 16), parseInt(colorString[3], 16)]
                    }
                }, {
                    re: /^#(\w{1})(\w{1})(\w{1})$/,
                    process: function(colorString) {
                        return [parseInt(colorString[1] + colorString[1], 16), parseInt(colorString[2] + colorString[2], 16), parseInt(colorString[3] + colorString[3], 16)]
                    }
                }];
        function Color(value) {
            this.baseColor = value;
            var color;
            if (value) {
                color = String(value).toLowerCase().replace(/ /g, '');
                color = standardColorNames[color] ? '#' + standardColorNames[color] : color;
                color = parseColor(color)
            }
            color = color || {};
            this.r = normalize(color[0]);
            this.g = normalize(color[1]);
            this.b = normalize(color[2])
        }
        function parseColor(color) {
            var result,
                i = 0,
                ii = standardColorTypes.length,
                str;
            for (; i < ii; ++i) {
                str = standardColorTypes[i].re.exec(color);
                if (str)
                    return standardColorTypes[i].process(str)
            }
            return null
        }
        function normalize(colorComponent) {
            return colorComponent < 0 || isNaN(colorComponent) ? 0 : colorComponent > 255 ? 255 : colorComponent
        }
        function toHexFromRgb(r, g, b) {
            return '#' + (0X01000000 | r << 16 | g << 8 | b).toString(16).slice(1)
        }
        var _round = Math.round;
        Color.prototype = {
            constructor: Color,
            highlight: function(step) {
                step = step || 10;
                return toHexFromRgb(normalize(this.r + step), normalize(this.g + step), normalize(this.b + step))
            },
            darken: function(step) {
                step = step || 10;
                return toHexFromRgb(normalize(this.r - step), normalize(this.g - step), normalize(this.b - step))
            },
            blend: function(blendColor, opacity) {
                var other = blendColor instanceof Color ? blendColor : new Color(blendColor),
                    result = new Color;
                result.r = normalize(_round(this.r * (1 - opacity) + other.r * opacity));
                result.g = normalize(_round(this.g * (1 - opacity) + other.g * opacity));
                result.b = normalize(_round(this.b * (1 - opacity) + other.b * opacity));
                return result
            },
            toHex: function() {
                return toHexFromRgb(this.r, this.g, this.b)
            }
        };
        DX.Color = Color
    })(DevExpress);
    /*! Module core, file localization.js */
    (function($, DX, undefined) {
        var localization = function() {
                var newMessages = {};
                return {
                        setup: function(localizablePrefix) {
                            this.localizeString = function(text) {
                                var regex = new RegExp("(^|[^a-zA-Z_0-9" + localizablePrefix + "-]+)(" + localizablePrefix + "{1,2})([a-zA-Z_0-9-]+)", "g"),
                                    escapeString = localizablePrefix + localizablePrefix;
                                return text.replace(regex, function(str, prefix, escape, localizationKey) {
                                        var result = prefix + localizablePrefix + localizationKey;
                                        if (escape !== escapeString)
                                            if (Globalize.cultures["default"].messages[localizationKey])
                                                result = prefix + Globalize.localize(localizationKey);
                                            else
                                                newMessages[localizationKey] = DX.inflector.humanize(localizationKey);
                                        return result
                                    })
                            }
                        },
                        localizeNode: function(node) {
                            var self = this;
                            $(node).each(function(index, nodeItem) {
                                if (!nodeItem.nodeType)
                                    return;
                                if (nodeItem.nodeType === 3)
                                    nodeItem.nodeValue = self.localizeString(nodeItem.nodeValue);
                                else {
                                    $.each(nodeItem.attributes || [], function(index, attr) {
                                        if (typeof attr.value === "string")
                                            attr.value = self.localizeString(attr.value)
                                    });
                                    $(nodeItem).contents().each(function(index, node) {
                                        self.localizeNode(node)
                                    })
                                }
                            })
                        },
                        getDictionary: function(onlyNew) {
                            if (onlyNew)
                                return newMessages;
                            return $.extend({}, newMessages, Globalize.cultures["default"].messages)
                        }
                    }
            }();
        localization.setup("@");
        DX.localization = localization
    })(jQuery, DevExpress);
    /*! Module core, file localization.en.js */
    Globalize.addCultureInfo("default", {messages: {
            Yes: "Yes",
            No: "No",
            Cancel: "Cancel",
            Clear: "Clear",
            Done: "Done",
            Loading: "Loading...",
            Select: "Select...",
            Search: "Search",
            Back: "Back",
            "dxLookup-searchPlaceholder": "Minimum character number: {0}",
            "dxCollectionContainerWidget-noDataText": "No data to display",
            "dxList-pullingDownText": "Pull down to refresh...",
            "dxList-pulledDownText": "Release to refresh...",
            "dxList-refreshingText": "Refreshing...",
            "dxList-pageLoadingText": "Loading...",
            "dxListEditDecorator-delete": "Delete",
            "dxScrollView-pullingDownText": "Pull down to refresh...",
            "dxScrollView-pulledDownText": "Release to refresh...",
            "dxScrollView-refreshingText": "Refreshing...",
            "dxScrollView-reachBottomText": "Loading...",
            "dxSwitch-onText": "ON",
            "dxSwitch-offText": "OFF"
        }});
    /*! Module core, file data.js */
    (function($, DX, undefined) {
        var HAS_KO = DX.support.hasKo;
        var bracketsToDots = function(expr) {
                return expr.replace(/\[/g, ".").replace(/\]/g, "")
            };
        var unwrapObservable = function(value) {
                if (HAS_KO)
                    return ko.utils.unwrapObservable(value);
                return value
            };
        var isObservable = function(value) {
                return HAS_KO && ko.isObservable(value)
            };
        var readPropValue = function(obj, propName) {
                if (propName === "this")
                    return obj;
                return obj[propName]
            };
        var assignPropValue = function(obj, propName, value) {
                if (propName === "this")
                    throw Error("Cannot assign to self");
                var propValue = obj[propName];
                if (isObservable(propValue))
                    propValue(value);
                else
                    obj[propName] = value
            };
        var compileGetter = function(expr) {
                if (arguments.length > 1)
                    expr = $.makeArray(arguments);
                if (!expr || expr === "this")
                    return function(obj) {
                            return obj
                        };
                if ($.isFunction(expr))
                    return expr;
                if ($.isArray(expr))
                    return combineGetters(expr);
                expr = bracketsToDots(expr);
                var path = expr.split(".");
                return function(obj, options) {
                        options = options || {};
                        var current = unwrapObservable(obj);
                        $.each(path, function() {
                            if (!current)
                                return false;
                            var next = unwrapObservable(current[this]);
                            if ($.isFunction(next) && !options.functionsAsIs)
                                next = next.call(current);
                            current = next
                        });
                        return current
                    }
            };
        var combineGetters = function(getters) {
                var compiledGetters = {};
                $.each(getters, function() {
                    compiledGetters[this] = compileGetter(this)
                });
                return function(obj, options) {
                        var result = {};
                        $.each(compiledGetters, function(name) {
                            var value = this(obj, options),
                                current,
                                path,
                                last,
                                i;
                            if (value === undefined)
                                return;
                            current = result;
                            path = name.split(".");
                            last = path.length - 1;
                            for (i = 0; i < last; i++)
                                current = current[path[i]] = {};
                            current[path[i]] = value
                        });
                        return result
                    }
            };
        var compileSetter = function(expr) {
                expr = expr || "this";
                expr = bracketsToDots(expr);
                var pos = expr.lastIndexOf("."),
                    targetGetter = compileGetter(expr.substr(0, pos)),
                    targetPropName = expr.substr(1 + pos);
                return function(obj, value, options) {
                        options = options || {};
                        var target = targetGetter(obj, {functionsAsIs: options.functionsAsIs}),
                            prevTargetValue = readPropValue(target, targetPropName);
                        if (!options.functionsAsIs && $.isFunction(prevTargetValue) && !isObservable(prevTargetValue))
                            target[targetPropName](value);
                        else {
                            prevTargetValue = unwrapObservable(prevTargetValue);
                            if (options.merge && $.isPlainObject(value) && (prevTargetValue === undefined || $.isPlainObject(prevTargetValue))) {
                                if (!prevTargetValue)
                                    assignPropValue(target, targetPropName, {});
                                DX.utils.deepExtendArraySafe(unwrapObservable(readPropValue(target, targetPropName)), value)
                            }
                            else
                                assignPropValue(target, targetPropName, value)
                        }
                    }
            };
        var normalizeBinaryCriterion = function(crit) {
                return [crit[0], crit.length < 3 ? "=" : crit[1].toLowerCase(), crit.length < 2 ? true : crit[crit.length - 1]]
            };
        var normalizeSortingInfo = function(info) {
                if (!$.isArray(info))
                    info = [info];
                return $.map(info, function(i) {
                        return {
                                selector: $.isFunction(i) || typeof i === "string" ? i : i.getter || i.field || i.selector,
                                desc: !!(i.desc || String(i.dir).charAt(0).toLowerCase() === "d")
                            }
                    })
            };
        var Guid = DX.Class.inherit({
                ctor: function(value) {
                    if (value)
                        value = String(value);
                    this._value = this._normalize(value || this._generate())
                },
                _normalize: function(value) {
                    value = value.replace(/[^a-f0-9]/ig, "").toLowerCase();
                    while (value.length < 32)
                        value += "0";
                    return [value.substr(0, 8), value.substr(8, 4), value.substr(12, 4), value.substr(16, 4), value.substr(20)].join("-")
                },
                _generate: function() {
                    var value = "";
                    for (var i = 0; i < 32; i++)
                        value += Math.round(Math.random() * 16).toString(16);
                    return value
                },
                toString: function() {
                    return this._value
                },
                valueOf: function() {
                    return this._value
                },
                toJSON: function() {
                    return this._value
                }
            });
        var toComparable = function(value, caseSensitive) {
                if (value instanceof Date)
                    return value.getTime();
                if (value instanceof Guid)
                    return value.valueOf();
                if (!caseSensitive && typeof value === "string")
                    return value.toLowerCase();
                return value
            };
        var keysEqual = function(keyExpr, key1, key2) {
                if ($.isArray(keyExpr)) {
                    var names = $.map(key1, function(v, k) {
                            return k
                        }),
                        name;
                    for (var i = 0; i < names.length; i++) {
                        name = names[i];
                        if (toComparable(key1[name], true) != toComparable(key2[name], true))
                            return false
                    }
                    return true
                }
                return toComparable(key1, true) == toComparable(key2, true)
            };
        var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
        var base64_encode = function(input) {
                if (!$.isArray(input))
                    input = stringToByteArray(String(input));
                var result = "";
                for (var i = 0; i < input.length; i += 3) {
                    var octet1 = input[i],
                        octet2 = input[i + 1],
                        octet3 = input[i + 2];
                    result += $.map([octet1 >> 2, (octet1 & 3) << 4 | octet2 >> 4, isNaN(octet2) ? 64 : (octet2 & 15) << 2 | octet3 >> 6, isNaN(octet3) ? 64 : octet3 & 63], function(item) {
                        return BASE64_CHARS.charAt(item)
                    }).join("")
                }
                return result
            };
        var stringToByteArray = function(str) {
                var bytes = [],
                    code,
                    i;
                for (i = 0; i < str.length; i++) {
                    code = str.charCodeAt(i);
                    if (code < 128)
                        bytes.push(code);
                    else if (code < 2048)
                        bytes.push(192 + (code >> 6), 128 + (code & 63));
                    else if (code < 65536)
                        bytes.push(224 + (code >> 12), 128 + (code >> 6 & 63), 128 + (code & 63));
                    else if (code < 2097152)
                        bytes.push(240 + (code >> 18), 128 + (code >> 12 & 63), 128 + (code >> 6 & 63), 128 + (code & 63))
                }
                return bytes
            };
        var errorMessageFromXhr = function() {
                var textStatusMessages = {
                        timeout: "Network connection timeout",
                        error: "Unspecified network error",
                        parsererror: "Unexpected server response"
                    };
                var textStatusDetails = {
                        timeout: "possible causes: the remote host is not accessible, overloaded or is not included into the domain white-list when being run in the native container",
                        error: "if the remote host is located on another domain, make sure it properly supports cross-origin resource sharing (CORS), or use the JSONP approach instead",
                        parsererror: "the remote host did not respond with valid JSON data"
                    };
                var explainTextStatus = function(textStatus) {
                        var result = textStatusMessages[textStatus];
                        if (!result)
                            return textStatus;
                        result += " (" + textStatusDetails[textStatus] + ")";
                        return result
                    };
                return function(xhr, textStatus) {
                        if (xhr.status < 400)
                            return explainTextStatus(textStatus);
                        return xhr.statusText
                    }
            }();
        var data = DX.data = {
                utils: {
                    compileGetter: compileGetter,
                    compileSetter: compileSetter,
                    normalizeBinaryCriterion: normalizeBinaryCriterion,
                    normalizeSortingInfo: normalizeSortingInfo,
                    toComparable: toComparable,
                    keysEqual: keysEqual,
                    errorMessageFromXhr: errorMessageFromXhr
                },
                Guid: Guid,
                base64_encode: base64_encode,
                queryImpl: {},
                queryAdapters: {},
                query: function() {
                    var impl = $.isArray(arguments[0]) ? "array" : "remote";
                    return data.queryImpl[impl].apply(this, arguments)
                },
                errorHandler: null,
                _handleError: function(error) {
                    if (window.console)
                        console.warn("[DevExpress.data]: " + error);
                    if (data.errorHandler)
                        data.errorHandler(error)
                }
            }
    })(jQuery, DevExpress);
    /*! Module core, file data.query.array.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            data = DX.data,
            queryImpl = data.queryImpl,
            compileGetter = data.utils.compileGetter,
            toComparable = data.utils.toComparable;
        var Iterator = Class.inherit({
                toArray: function() {
                    var result = [];
                    this.reset();
                    while (this.next())
                        result.push(this.current());
                    return result
                },
                countable: function() {
                    return false
                }
            });
        var ArrayIterator = Iterator.inherit({
                ctor: function(array) {
                    this.array = array;
                    this.index = -1
                },
                next: function() {
                    if (this.index + 1 < this.array.length) {
                        this.index++;
                        return true
                    }
                    return false
                },
                current: function() {
                    return this.array[this.index]
                },
                reset: function() {
                    this.index = -1
                },
                toArray: function() {
                    return this.array.slice(0)
                },
                countable: function() {
                    return true
                },
                count: function() {
                    return this.array.length
                }
            });
        var WrappedIterator = Iterator.inherit({
                ctor: function(iter) {
                    this.iter = iter
                },
                next: function() {
                    return this.iter.next()
                },
                current: function() {
                    return this.iter.current()
                },
                reset: function() {
                    return this.iter.reset()
                }
            });
        var SortIterator = Iterator.inherit({
                ctor: function(iter, getter, desc) {
                    this.iter = iter;
                    this.rules = [{
                            getter: getter,
                            desc: desc
                        }]
                },
                thenBy: function(getter, desc) {
                    var result = new SortIterator(this.sortedIter || this.iter, getter, desc);
                    if (!this.sortedIter)
                        result.rules = this.rules.concat(result.rules);
                    return result
                },
                next: function() {
                    this._ensureSorted();
                    return this.sortedIter.next()
                },
                current: function() {
                    this._ensureSorted();
                    return this.sortedIter.current()
                },
                reset: function() {
                    delete this.sortedIter
                },
                countable: function() {
                    return this.sortedIter || this.iter.countable()
                },
                count: function() {
                    if (this.sortedIter)
                        return this.sortedIter.count();
                    return this.iter.count()
                },
                _ensureSorted: function() {
                    if (this.sortedIter)
                        return;
                    $.each(this.rules, function() {
                        this.getter = compileGetter(this.getter)
                    });
                    this.sortedIter = new ArrayIterator(this.iter.toArray().sort($.proxy(this._compare, this)))
                },
                _compare: function(x, y) {
                    if (x === y)
                        return 0;
                    for (var i = 0, rulesCount = this.rules.length; i < rulesCount; i++) {
                        var rule = this.rules[i],
                            xValue = toComparable(rule.getter(x)),
                            yValue = toComparable(rule.getter(y)),
                            factor = rule.desc ? -1 : 1;
                        if (xValue < yValue)
                            return -factor;
                        if (xValue > yValue)
                            return factor;
                        if (xValue !== yValue)
                            return !xValue ? -factor : factor
                    }
                    return 0
                }
            });
        var compileCriteria = function() {
                var compileGroup = function(crit) {
                        var operands = [],
                            bag = ["return function(d) { return "],
                            index = 0,
                            pushAnd = false;
                        $.each(crit, function() {
                            if ($.isArray(this) || $.isFunction(this)) {
                                if (pushAnd)
                                    bag.push(" && ");
                                operands.push(compileCriteria(this));
                                bag.push("op[", index, "](d)");
                                index++;
                                pushAnd = true
                            }
                            else {
                                bag.push(/and|&/i.test(this) ? " && " : " || ");
                                pushAnd = false
                            }
                        });
                        bag.push(" }");
                        return new Function("op", bag.join(""))(operands)
                    };
                var toString = function(value) {
                        return DX.utils.isDefined(value) ? value.toString() : ''
                    };
                var compileBinary = function(crit) {
                        crit = data.utils.normalizeBinaryCriterion(crit);
                        var getter = compileGetter(crit[0]),
                            op = crit[1],
                            value = crit[2];
                        value = toComparable(value);
                        switch (op.toLowerCase()) {
                            case"=":
                                return function(obj) {
                                        return toComparable(getter(obj)) == value
                                    };
                            case"<>":
                                return function(obj) {
                                        return toComparable(getter(obj)) != value
                                    };
                            case">":
                                return function(obj) {
                                        return toComparable(getter(obj)) > value
                                    };
                            case"<":
                                return function(obj) {
                                        return toComparable(getter(obj)) < value
                                    };
                            case">=":
                                return function(obj) {
                                        return toComparable(getter(obj)) >= value
                                    };
                            case"<=":
                                return function(obj) {
                                        return toComparable(getter(obj)) <= value
                                    };
                            case"startswith":
                                return function(obj) {
                                        return toComparable(toString(getter(obj))).indexOf(value) === 0
                                    };
                            case"endswith":
                                return function(obj) {
                                        var getterValue = toComparable(toString(getter(obj)));
                                        return getterValue.lastIndexOf(value) === getterValue.length - toString(value).length
                                    };
                            case"contains":
                                return function(obj) {
                                        return toComparable(toString(getter(obj))).indexOf(value) > -1
                                    };
                            case"notcontains":
                                return function(obj) {
                                        return toComparable(toString(getter(obj))).indexOf(value) === -1
                                    }
                        }
                        throw Error("Unknown filter operation: " + op);
                    };
                return function(crit) {
                        if ($.isFunction(crit))
                            return crit;
                        if ($.isArray(crit[0]))
                            return compileGroup(crit);
                        return compileBinary(crit)
                    }
            }();
        var FilterIterator = WrappedIterator.inherit({
                ctor: function(iter, criteria) {
                    this.callBase(iter);
                    this.criteria = compileCriteria(criteria)
                },
                next: function() {
                    while (this.iter.next())
                        if (this.criteria(this.current()))
                            return true;
                    return false
                }
            });
        var GroupIterator = Iterator.inherit({
                ctor: function(iter, getter) {
                    this.iter = iter;
                    this.getter = getter
                },
                next: function() {
                    this._ensureGrouped();
                    return this.groupedIter.next()
                },
                current: function() {
                    this._ensureGrouped();
                    return this.groupedIter.current()
                },
                reset: function() {
                    delete this.groupedIter
                },
                countable: function() {
                    return !!this.groupedIter
                },
                count: function() {
                    return this.groupedIter.count()
                },
                _ensureGrouped: function() {
                    if (this.groupedIter)
                        return;
                    var hash = {},
                        keys = [],
                        iter = this.iter,
                        getter = compileGetter(this.getter);
                    iter.reset();
                    while (iter.next()) {
                        var current = iter.current(),
                            key = getter(current);
                        if (key in hash)
                            hash[key].push(current);
                        else {
                            hash[key] = [current];
                            keys.push(key)
                        }
                    }
                    this.groupedIter = new ArrayIterator($.map(keys, function(key) {
                        return {
                                key: key,
                                items: hash[key]
                            }
                    }))
                }
            });
        var SelectIterator = WrappedIterator.inherit({
                ctor: function(iter, getter) {
                    this.callBase(iter);
                    this.getter = compileGetter(getter)
                },
                current: function() {
                    return this.getter(this.callBase())
                },
                countable: function() {
                    return this.iter.countable()
                },
                count: function() {
                    return this.iter.count()
                }
            });
        var SliceIterator = WrappedIterator.inherit({
                ctor: function(iter, skip, take) {
                    this.callBase(iter);
                    this.skip = Math.max(0, skip);
                    this.take = Math.max(0, take);
                    this.pos = 0
                },
                next: function() {
                    if (this.pos >= this.skip + this.take)
                        return false;
                    while (this.pos < this.skip && this.iter.next())
                        this.pos++;
                    this.pos++;
                    return this.iter.next()
                },
                reset: function() {
                    this.callBase();
                    this.pos = 0
                },
                countable: function() {
                    return this.iter.countable()
                },
                count: function() {
                    return Math.min(this.iter.count() - this.skip, this.take)
                }
            });
        queryImpl.array = function(iter, queryOptions) {
            queryOptions = queryOptions || {};
            if (!(iter instanceof Iterator))
                iter = new ArrayIterator(iter);
            var handleError = function(error) {
                    var handler = queryOptions.errorHandler;
                    if (handler)
                        handler(error);
                    data._handleError(error)
                };
            var aggregate = function(seed, step, finalize) {
                    var d = $.Deferred().fail(handleError);
                    try {
                        iter.reset();
                        if (arguments.length < 2) {
                            step = arguments[0];
                            seed = iter.next() ? iter.current() : undefined
                        }
                        var accumulator = seed;
                        while (iter.next())
                            accumulator = step(accumulator, iter.current());
                        d.resolve(finalize ? finalize(accumulator) : accumulator)
                    }
                    catch(x) {
                        d.reject(x)
                    }
                    return d.promise()
                };
            var select = function(getter) {
                    if (!$.isFunction(getter) && !$.isArray(getter))
                        getter = $.makeArray(arguments);
                    return chainQuery(new SelectIterator(iter, getter))
                };
            var selectProp = function(name) {
                    return select(compileGetter(name))
                };
            var chainQuery = function(iter) {
                    return queryImpl.array(iter, queryOptions)
                };
            return {
                    toArray: function() {
                        return iter.toArray()
                    },
                    enumerate: function() {
                        var d = $.Deferred().fail(handleError);
                        try {
                            d.resolve(iter.toArray())
                        }
                        catch(x) {
                            d.reject(x)
                        }
                        return d.promise()
                    },
                    sortBy: function(getter, desc) {
                        return chainQuery(new SortIterator(iter, getter, desc))
                    },
                    thenBy: function(getter, desc) {
                        if (iter instanceof SortIterator)
                            return chainQuery(iter.thenBy(getter, desc));
                        throw Error();
                    },
                    filter: function(criteria) {
                        if (!$.isArray(criteria))
                            criteria = $.makeArray(arguments);
                        return chainQuery(new FilterIterator(iter, criteria))
                    },
                    slice: function(skip, take) {
                        if (take === undefined)
                            take = Number.MAX_VALUE;
                        return chainQuery(new SliceIterator(iter, skip, take))
                    },
                    select: select,
                    groupBy: function(getter) {
                        return chainQuery(new GroupIterator(iter, getter))
                    },
                    aggregate: aggregate,
                    count: function() {
                        if (iter.countable()) {
                            var d = $.Deferred().fail(handleError);
                            try {
                                d.resolve(iter.count())
                            }
                            catch(x) {
                                d.reject(x)
                            }
                            return d.promise()
                        }
                        return aggregate(0, function(count) {
                                return 1 + count
                            })
                    },
                    sum: function(getter) {
                        if (getter)
                            return selectProp(getter).sum();
                        return aggregate(0, function(sum, item) {
                                return sum + item
                            })
                    },
                    min: function(getter) {
                        if (getter)
                            return selectProp(getter).min();
                        return aggregate(function(min, item) {
                                return item < min ? item : min
                            })
                    },
                    max: function(getter) {
                        if (getter)
                            return selectProp(getter).max();
                        return aggregate(function(max, item) {
                                return item > max ? item : max
                            })
                    },
                    avg: function(getter) {
                        if (getter)
                            return selectProp(getter).avg();
                        var count = 0;
                        return aggregate(0, function(sum, item) {
                                count++;
                                return sum + item
                            }, function(sum) {
                                return count ? sum / count : undefined
                            })
                    }
                }
        }
    })(jQuery, DevExpress);
    /*! Module core, file data.query.remote.js */
    (function($, DX, undefined) {
        var data = DX.data,
            queryImpl = data.queryImpl;
        queryImpl.remote = function(url, queryOptions, tasks) {
            tasks = tasks || [];
            queryOptions = queryOptions || {};
            var createTask = function(name, args) {
                    return {
                            name: name,
                            args: args
                        }
                };
            var exec = function(executorTask) {
                    var d = $.Deferred(),
                        adapterFactory,
                        adapter,
                        taskQueue,
                        currentTask;
                    var rejectWithNotify = function(error) {
                            var handler = queryOptions.errorHandler;
                            if (handler)
                                handler(error);
                            data._handleError(error);
                            d.reject(error)
                        };
                    try {
                        adapterFactory = queryOptions.adapter || "odata";
                        if (!$.isFunction(adapterFactory))
                            adapterFactory = data.queryAdapters[adapterFactory];
                        adapter = adapterFactory(queryOptions);
                        taskQueue = [].concat(tasks).concat(executorTask);
                        while (taskQueue.length) {
                            currentTask = taskQueue[0];
                            if (String(currentTask.name) !== "enumerate")
                                if (!adapter[currentTask.name] || adapter[currentTask.name].apply(adapter, currentTask.args) === false)
                                    break;
                            taskQueue.shift()
                        }
                        adapter.exec(url).done(function(result, extra) {
                            if (!taskQueue.length)
                                d.resolve(result, extra);
                            else {
                                var clientChain = queryImpl.array(result, {errorHandler: queryOptions.errorHandler});
                                $.each(taskQueue, function() {
                                    clientChain = clientChain[this.name].apply(clientChain, this.args)
                                });
                                clientChain.done($.proxy(d.resolve, d)).fail($.proxy(d.reject, d))
                            }
                        }).fail(rejectWithNotify)
                    }
                    catch(x) {
                        rejectWithNotify(x)
                    }
                    return d.promise()
                };
            var query = {};
            $.each(["sortBy", "thenBy", "filter", "slice", "select", "groupBy"], function() {
                var name = this;
                query[name] = function() {
                    return queryImpl.remote(url, queryOptions, tasks.concat(createTask(name, arguments)))
                }
            });
            $.each(["count", "min", "max", "sum", "avg", "aggregate", "enumerate"], function() {
                var name = this;
                query[name] = function() {
                    return exec.call(this, createTask(name, arguments))
                }
            });
            return query
        }
    })(jQuery, DevExpress);
    /*! Module core, file data.odata.js */
    (function($, DX, undefined) {
        var data = DX.data,
            Guid = data.Guid;
        var JSON_VERBOSE_MIME_TYPE = "application/json;odata=verbose";
        var ajaxOptionsForRequest = function(request, requestOptions) {
                request = $.extend({
                    method: "get",
                    url: "",
                    params: {},
                    payload: null,
                    headers: {}
                }, request);
                requestOptions = requestOptions || {};
                var beforeSend = requestOptions.beforeSend;
                if (beforeSend)
                    beforeSend(request);
                var method = (request.method || "get").toLowerCase(),
                    isGet = method === "get",
                    useJsonp = isGet && requestOptions.jsonp,
                    params = $.extend({}, request.params),
                    ajaxData = isGet ? params : JSON.stringify(request.payload),
                    qs = !isGet && $.param(params),
                    url = request.url,
                    contentType = !isGet && JSON_VERBOSE_MIME_TYPE;
                if (qs)
                    url += (url.indexOf("?") > -1 ? "&" : "?") + qs;
                if (useJsonp)
                    ajaxData["$format"] = "json";
                return {
                        url: url,
                        data: ajaxData,
                        dataType: useJsonp ? "jsonp" : "json",
                        jsonp: useJsonp && "$callback",
                        type: method,
                        timeout: 30000,
                        headers: request.headers,
                        contentType: contentType,
                        accepts: {json: [JSON_VERBOSE_MIME_TYPE, "text/plain"].join()},
                        xhrFields: {withCredentials: requestOptions.withCredentials}
                    }
            };
        var sendRequest = function(request, requestOptions) {
                var d = $.Deferred();
                $.ajax(ajaxOptionsForRequest(request, requestOptions)).always(function(obj, textStatus) {
                    var tuplet = interpretVerboseJsonFormat(obj, textStatus),
                        error = tuplet.error,
                        data = tuplet.data,
                        nextUrl = tuplet.nextUrl,
                        extra;
                    if (error)
                        d.reject(error);
                    else if (requestOptions.countOnly)
                        d.resolve(tuplet.count);
                    else if (nextUrl)
                        sendRequest({url: nextUrl}, requestOptions).fail($.proxy(d.reject, d)).done(function(nextData) {
                            d.resolve(data.concat(nextData))
                        });
                    else {
                        if (isFinite(tuplet.count))
                            extra = {totalCount: tuplet.count};
                        d.resolve(data, extra)
                    }
                });
                return d.promise()
            };
        var formatDotNetError = function(errorObj) {
                var message,
                    currentError = errorObj;
                if ("message" in errorObj)
                    if (errorObj.message.value)
                        message = errorObj.message.value;
                    else
                        message = errorObj.message;
                while (currentError = currentError.innererror || currentError.internalexception) {
                    message = currentError.message;
                    if (currentError.internalexception && message.indexOf("inner exception") === -1)
                        break
                }
                return message
            };
        var errorFromResponse = function(obj, textStatus) {
                if (textStatus === "nocontent")
                    return null;
                var httpStatus = 200,
                    message = "Unknown error",
                    response = obj;
                if (textStatus !== "success") {
                    httpStatus = obj.status;
                    message = data.utils.errorMessageFromXhr(obj, textStatus);
                    try {
                        response = $.parseJSON(obj.responseText)
                    }
                    catch(x) {}
                }
                var errorObj = response && response.error;
                if (errorObj) {
                    message = formatDotNetError(errorObj) || message;
                    if (httpStatus === 200)
                        httpStatus = 500;
                    if (response.error.code)
                        httpStatus = Number(response.error.code);
                    return $.extend(Error(message), {
                            httpStatus: httpStatus,
                            errorDetails: errorObj
                        })
                }
                else if (httpStatus !== 200)
                    return $.extend(Error(message), {httpStatus: httpStatus})
            };
        var interpretVerboseJsonFormat = function(obj, textStatus) {
                var error = errorFromResponse(obj, textStatus);
                if (error)
                    return {error: error};
                if (!$.isPlainObject(obj))
                    return {data: obj};
                var data = obj.d;
                if (!data)
                    return {error: Error("Malformed or unsupported JSON response received")};
                data = data.results || data;
                recognizeDates(data);
                return {
                        data: data,
                        nextUrl: obj.d.__next,
                        count: obj.d.__count
                    }
            };
        var EdmLiteral = DX.Class.inherit({
                ctor: function(value) {
                    this._value = value
                },
                valueOf: function() {
                    return this._value
                }
            });
        var serializeDate = function() {
                var pad = function(part) {
                        part = String(part);
                        if (part.length < 2)
                            part = "0" + part;
                        return part
                    };
                return function(date) {
                        var result = ["datetime'", date.getUTCFullYear(), "-", pad(date.getUTCMonth() + 1), "-", pad(date.getUTCDate())];
                        if (date.getUTCHours() || date.getUTCMinutes() || date.getUTCSeconds() || date.getUTCMilliseconds()) {
                            result.push("T", pad(date.getUTCHours()), ":", pad(date.getUTCMinutes()), ":", pad(date.getUTCSeconds()));
                            if (date.getUTCMilliseconds())
                                result.push(".", date.getUTCMilliseconds())
                        }
                        result.push("'");
                        return result.join("")
                    }
            }();
        var serializePropName = function(propName) {
                if (propName instanceof EdmLiteral)
                    return propName.valueOf();
                return propName.replace(/\./g, "/")
            };
        var serializeValue = function(value) {
                if (value instanceof Date)
                    return serializeDate(value);
                if (value instanceof Guid)
                    return "guid'" + value + "'";
                if (value instanceof EdmLiteral)
                    return value.valueOf();
                if (typeof value === "string")
                    return "'" + value.replace(/'/g, "''") + "'";
                return String(value)
            };
        var serializeKey = function(key) {
                if ($.isPlainObject(key)) {
                    var parts = [];
                    $.each(key, function(k, v) {
                        parts.push(serializePropName(k) + "=" + serializeValue(v))
                    });
                    return parts.join()
                }
                return serializeValue(key)
            };
        var recognizeDates = function(list) {
                $.each(list, function(i, val) {
                    if (val !== null && typeof val === "object")
                        recognizeDates(val);
                    else if (typeof val === "string") {
                        var matches = val.match(/^\/Date\((-?\d+)((\+|-)?(\d+)?)\)\/$/);
                        if (matches)
                            list[i] = new Date(Number(matches[1]) + matches[2] * 60000)
                    }
                })
            };
        var keyConverters = {
                String: function(value) {
                    return value + ""
                },
                Int32: function(value) {
                    return ~~value
                },
                Int64: function(value) {
                    if (value instanceof EdmLiteral)
                        return value;
                    return new EdmLiteral(value + "L")
                },
                Guid: function(value) {
                    if (value instanceof Guid)
                        return value;
                    return new Guid(value)
                }
            };
        var compileCriteria = function() {
                var createBinaryOperationFormatter = function(op) {
                        return function(prop, val, bag) {
                                bag.push(prop, " ", op, " ", val)
                            }
                    };
                var createStringFuncFormatter = function(op, reverse) {
                        return function(prop, val, bag) {
                                if (reverse)
                                    bag.push(op, "(", val, ",", prop, ")");
                                else
                                    bag.push(op, "(", prop, ",", val, ")")
                            }
                    };
                var formatters = {
                        "=": createBinaryOperationFormatter("eq"),
                        "<>": createBinaryOperationFormatter("ne"),
                        ">": createBinaryOperationFormatter("gt"),
                        ">=": createBinaryOperationFormatter("ge"),
                        "<": createBinaryOperationFormatter("lt"),
                        "<=": createBinaryOperationFormatter("le"),
                        startswith: createStringFuncFormatter("startswith"),
                        endswith: createStringFuncFormatter("endswith"),
                        contains: createStringFuncFormatter("substringof", true),
                        notcontains: createStringFuncFormatter("not substringof", true)
                    };
                var compileBinary = function(criteria, bag) {
                        criteria = data.utils.normalizeBinaryCriterion(criteria);
                        var op = criteria[1],
                            formatter = formatters[op.toLowerCase()];
                        if (!formatter)
                            throw Error("Unknown filter operation: " + op);
                        formatter(serializePropName(criteria[0]), serializeValue(criteria[2]), bag)
                    };
                var compileGroup = function(criteria, bag) {
                        var pushAnd = false;
                        $.each(criteria, function() {
                            if ($.isArray(this)) {
                                if (pushAnd)
                                    bag.push(" and ");
                                bag.push("(");
                                compileCore(this, bag);
                                bag.push(")");
                                pushAnd = true
                            }
                            else {
                                bag.push(/and|&/i.test(this) ? " and " : " or ");
                                pushAnd = false
                            }
                        })
                    };
                var compileCore = function(criteria, bag) {
                        if ($.isArray(criteria[0]))
                            compileGroup(criteria, bag);
                        else
                            compileBinary(criteria, bag)
                    };
                return function(criteria) {
                        var bag = [];
                        compileCore(criteria, bag);
                        return bag.join("")
                    }
            }();
        var createODataQueryAdapter = function(queryOptions) {
                var sorting = [],
                    criteria = [],
                    select,
                    skip,
                    take,
                    countQuery;
                var hasSlice = function() {
                        return skip || take !== undefined
                    };
                var sortCore = function(getter, desc, reset) {
                        if (hasSlice() || typeof getter !== "string")
                            return false;
                        if (reset)
                            sorting = [];
                        var rule = serializePropName(getter);
                        if (desc)
                            rule += " desc";
                        sorting.push(rule)
                    };
                var generateExpand = function() {
                        var hash = {};
                        if (queryOptions.expand)
                            $.each($.makeArray(queryOptions.expand), function() {
                                hash[serializePropName(this)] = 1
                            });
                        if (select)
                            $.each(select, function() {
                                var path = this.split(".");
                                if (path.length < 2)
                                    return;
                                path.pop();
                                hash[serializePropName(path.join("."))] = 1
                            });
                        return $.map(hash, function(k, v) {
                                return v
                            }).join() || undefined
                    };
                var requestData = function() {
                        var result = {};
                        if (!countQuery) {
                            if (sorting.length)
                                result["$orderby"] = sorting.join(",");
                            if (skip)
                                result["$skip"] = skip;
                            if (take !== undefined)
                                result["$top"] = take;
                            if (select)
                                result["$select"] = serializePropName(select.join());
                            result["$expand"] = generateExpand()
                        }
                        if (criteria.length)
                            result["$filter"] = compileCriteria(criteria.length < 2 ? criteria[0] : criteria);
                        if (countQuery)
                            result["$top"] = 0;
                        if (queryOptions.requireTotalCount || countQuery)
                            result["$inlinecount"] = "allpages";
                        return result
                    };
                return {
                        exec: function(url) {
                            return sendRequest({
                                    url: url,
                                    params: $.extend(requestData(), queryOptions && queryOptions.params)
                                }, {
                                    beforeSend: queryOptions.beforeSend,
                                    jsonp: queryOptions.jsonp,
                                    withCredentials: queryOptions.withCredentials,
                                    countOnly: countQuery
                                })
                        },
                        sortBy: function(getter, desc) {
                            return sortCore(getter, desc, true)
                        },
                        thenBy: function(getter, desc) {
                            return sortCore(getter, desc, false)
                        },
                        slice: function(skipCount, takeCount) {
                            if (hasSlice())
                                return false;
                            skip = skipCount;
                            take = takeCount
                        },
                        filter: function(criterion) {
                            if (hasSlice() || $.isFunction(criterion))
                                return false;
                            if (!$.isArray(criterion))
                                criterion = $.makeArray(arguments);
                            if (criteria.length)
                                criteria.push("and");
                            criteria.push(criterion)
                        },
                        select: function(expr) {
                            if (select || $.isFunction(expr))
                                return false;
                            if (!$.isArray(expr))
                                expr = $.makeArray(arguments);
                            select = expr
                        },
                        count: function() {
                            countQuery = true
                        }
                    }
            };
        $.extend(true, data, {
            EdmLiteral: EdmLiteral,
            utils: {odata: {
                    sendRequest: sendRequest,
                    serializePropName: serializePropName,
                    serializeValue: serializeValue,
                    serializeKey: serializeKey,
                    keyConverters: keyConverters
                }},
            queryAdapters: {odata: createODataQueryAdapter}
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.store.abstract.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            abstract = DX.abstract,
            data = DX.data,
            normalizeSortingInfo = data.utils.normalizeSortingInfo;
        var STORE_CALLBACK_NAMES = ["loading", "loaded", "modifying", "modified", "inserting", "inserted", "updating", "updated", "removing", "removed"];
        function multiLevelGroup(query, groupInfo) {
            query = query.groupBy(groupInfo[0].selector);
            if (groupInfo.length > 1)
                query = query.select(function(g) {
                    return $.extend({}, g, {items: multiLevelGroup(data.query(g.items), groupInfo.slice(1)).toArray()})
                });
            return query
        }
        data.Store = Class.inherit({
            ctor: function(options) {
                var self = this;
                options = options || {};
                $.each(STORE_CALLBACK_NAMES, function() {
                    var callbacks = self[this] = $.Callbacks();
                    if (this in options)
                        callbacks.add(options[this])
                });
                this._key = options.key;
                this._errorHandler = options.errorHandler;
                this._useDefaultSearch = true
            },
            _customLoadOptions: function() {
                return null
            },
            key: function() {
                return this._key
            },
            keyOf: function(obj) {
                if (!this._keyGetter)
                    this._keyGetter = data.utils.compileGetter(this.key());
                return this._keyGetter(obj)
            },
            _requireKey: function() {
                if (!this.key())
                    throw Error("Key expression is required for this operation");
            },
            load: function(options) {
                var self = this;
                options = options || {};
                this.loading.fire(options);
                return this._loadImpl(options).done(function(result, extra) {
                        self.loaded.fire(result, extra)
                    })
            },
            _loadImpl: function(options) {
                var filter = options.filter,
                    sort = options.sort,
                    select = options.select,
                    group = options.group,
                    skip = options.skip,
                    take = options.take,
                    q = this.createQuery(options);
                if (filter)
                    q = q.filter(filter);
                if (group)
                    group = normalizeSortingInfo(group);
                if (sort || group) {
                    sort = normalizeSortingInfo(sort || []);
                    if (group)
                        sort = group.concat(sort);
                    $.each(sort, function(index) {
                        q = q[index ? "thenBy" : "sortBy"](this.selector, this.desc)
                    })
                }
                if (select)
                    q = q.select(select);
                if (group)
                    q = multiLevelGroup(q, group);
                if (take || skip)
                    q = q.slice(skip || 0, take);
                return q.enumerate()
            },
            createQuery: abstract,
            totalCount: function(options) {
                return this._addFailHandlers(this._totalCountImpl(options))
            },
            _totalCountImpl: function(options) {
                options = options || {};
                var q = this.createQuery(),
                    group = options.group,
                    filter = options.filter;
                if (filter)
                    q = q.filter(filter);
                if (group) {
                    group = normalizeSortingInfo(group);
                    q = multiLevelGroup(q, group)
                }
                return q.count()
            },
            byKey: function(key, extraOptions) {
                return this._addFailHandlers(this._byKeyImpl(key, extraOptions))
            },
            _byKeyImpl: abstract,
            insert: function(values) {
                var self = this;
                self.modifying.fire();
                self.inserting.fire(values);
                return self._addFailHandlers(self._insertImpl(values).done(function(callbackValues, callbackKey) {
                        self.inserted.fire(callbackValues, callbackKey);
                        self.modified.fire()
                    }))
            },
            _insertImpl: abstract,
            update: function(key, values) {
                var self = this;
                self.modifying.fire();
                self.updating.fire(key, values);
                return self._addFailHandlers(self._updateImpl(key, values).done(function(callbackKey, callbackValues) {
                        self.updated.fire(callbackKey, callbackValues);
                        self.modified.fire()
                    }))
            },
            _updateImpl: abstract,
            remove: function(key) {
                var self = this;
                self.modifying.fire();
                self.removing.fire(key);
                return self._addFailHandlers(self._removeImpl(key).done(function(callbackKey) {
                        self.removed.fire(callbackKey);
                        self.modified.fire()
                    }))
            },
            _removeImpl: abstract,
            _addFailHandlers: function(deferred) {
                return deferred.fail(this._errorHandler, data._handleError)
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.store.array.js */
    (function($, DX, undefined) {
        var data = DX.data,
            Guid = data.Guid;
        var trivialPromise = function(_) {
                var d = $.Deferred();
                return d.resolve.apply(d, arguments).promise()
            };
        var rejectedPromise = function(_) {
                var d = $.Deferred();
                return d.reject.apply(d, arguments).promise()
            };
        data.ArrayStore = data.Store.inherit({
            ctor: function(options) {
                if ($.isArray(options))
                    options = {data: options};
                else
                    options = options || {};
                this.callBase(options);
                this._array = options.data || []
            },
            createQuery: function() {
                return data.query(this._array, {errorHandler: this._errorHandler})
            },
            _byKeyImpl: function(key) {
                return trivialPromise(this._array[this._indexByKey(key)])
            },
            _insertImpl: function(values) {
                var keyExpr = this.key(),
                    keyValue,
                    obj = {};
                $.extend(obj, values);
                if (keyExpr) {
                    keyValue = this.keyOf(obj);
                    if (keyValue === undefined || typeof keyValue === "object" && $.isEmptyObject(keyValue)) {
                        if ($.isArray(keyExpr))
                            throw Error("Compound keys cannot be auto-generated");
                        keyValue = obj[keyExpr] = String(new Guid)
                    }
                    else if (this._array[this._indexByKey(keyValue)] !== undefined)
                        return rejectedPromise(Error("Attempt to insert an item with the duplicate key"))
                }
                else
                    keyValue = obj;
                this._array.push(obj);
                return trivialPromise(values, keyValue)
            },
            _updateImpl: function(key, values) {
                var target;
                if (this.key()) {
                    var index = this._indexByKey(key);
                    if (index < 0)
                        return rejectedPromise(Error("Data item not found"));
                    target = this._array[index]
                }
                else
                    target = key;
                DX.utils.deepExtendArraySafe(target, values);
                return trivialPromise(key, values)
            },
            _removeImpl: function(key) {
                var index = this._indexByKey(key);
                if (index > -1)
                    this._array.splice(index, 1);
                return trivialPromise(key)
            },
            _indexByKey: function(key) {
                for (var i = 0, arrayLength = this._array.length; i < arrayLength; i++)
                    if (data.utils.keysEqual(this.key(), this.keyOf(this._array[i]), key))
                        return i;
                return -1
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.store.local.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            abstract = DX.abstract,
            data = DX.data;
        var LocalStoreBackend = Class.inherit({
                ctor: function(store, storeOptions) {
                    this._store = store;
                    this._dirty = false;
                    var immediate = this._immediate = storeOptions.immediate;
                    var flushInterval = Math.max(100, storeOptions.flushInterval || 10 * 1000);
                    if (!immediate) {
                        var saveProxy = $.proxy(this.save, this);
                        setInterval(saveProxy, flushInterval);
                        $(window).on("beforeunload", saveProxy);
                        if (window.cordova)
                            document.addEventListener("pause", saveProxy, false)
                    }
                },
                notifyChanged: function() {
                    this._dirty = true;
                    if (this._immediate)
                        this.save()
                },
                load: function() {
                    this._store._array = this._loadImpl();
                    this._dirty = false
                },
                save: function() {
                    if (!this._dirty)
                        return;
                    this._saveImpl(this._store._array);
                    this._dirty = false
                },
                _loadImpl: abstract,
                _saveImpl: abstract
            });
        var DomLocalStoreBackend = LocalStoreBackend.inherit({
                ctor: function(store, storeOptions) {
                    this.callBase(store, storeOptions);
                    var name = storeOptions.name;
                    if (!name)
                        throw Error("Name is required");
                    this._key = "dx-data-localStore-" + name
                },
                _loadImpl: function() {
                    var raw = localStorage.getItem(this._key);
                    if (raw)
                        return JSON.parse(raw);
                    return []
                },
                _saveImpl: function(array) {
                    if (!array.length)
                        localStorage.removeItem(this._key);
                    else
                        localStorage.setItem(this._key, JSON.stringify(array))
                }
            });
        var localStoreBackends = {dom: DomLocalStoreBackend};
        data.LocalStore = data.ArrayStore.inherit({
            ctor: function(options) {
                if (typeof options === "string")
                    options = {name: options};
                else
                    options = options || {};
                this.callBase(options);
                this._backend = new localStoreBackends[options.backend || "dom"](this, options);
                this._backend.load()
            },
            clear: function() {
                this._array = [];
                this._backend.notifyChanged()
            },
            _insertImpl: function(values) {
                var b = this._backend;
                return this.callBase(values).done($.proxy(b.notifyChanged, b))
            },
            _updateImpl: function(key, values) {
                var b = this._backend;
                return this.callBase(key, values).done($.proxy(b.notifyChanged, b))
            },
            _removeImpl: function(key) {
                var b = this._backend;
                return this.callBase(key).done($.proxy(b.notifyChanged, b))
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.store.odata.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            data = DX.data,
            odataUtils = data.utils.odata;
        var escapeServiceOperationParams = function(params) {
                if (!params)
                    return params;
                var result = {};
                $.each(params, function(k, v) {
                    result[k] = odataUtils.serializeValue(v)
                });
                return result
            };
        var convertSimpleKey = function(keyType, keyValue) {
                var converter = odataUtils.keyConverters[keyType];
                if (!converter)
                    throw Error("Unknown key type: " + keyType);
                return converter(keyValue)
            };
        var SharedMethods = {
                _extractServiceOptions: function(options) {
                    options = options || {};
                    this._url = String(options.url).replace(/\/+$/, "");
                    this._beforeSend = options.beforeSend;
                    this._jsonp = options.jsonp;
                    this._withCredentials = options.withCredentials
                },
                _sendRequest: function(url, method, params, payload) {
                    return odataUtils.sendRequest({
                            url: url,
                            method: method,
                            params: params || {},
                            payload: payload
                        }, {
                            beforeSend: this._beforeSend,
                            jsonp: this._jsonp,
                            withCredentials: this._withCredentials
                        })
                }
            };
        var ODataStore = data.Store.inherit({
                ctor: function(options) {
                    this.callBase(options);
                    this._extractServiceOptions(options);
                    this._keyType = options.keyType
                },
                _customLoadOptions: function() {
                    return ["expand", "customQueryParams"]
                },
                _byKeyImpl: function(key, extraOptions) {
                    var params = {};
                    if (extraOptions)
                        if (extraOptions.expand)
                            params["$expand"] = $.map($.makeArray(extraOptions.expand), odataUtils.serializePropName).join();
                    return this._sendRequest(this._byKeyUrl(key), "GET", params)
                },
                createQuery: function(loadOptions) {
                    loadOptions = loadOptions || {};
                    return data.query(this._url, {
                            beforeSend: this._beforeSend,
                            errorHandler: this._errorHandler,
                            jsonp: this._jsonp,
                            withCredentials: this._withCredentials,
                            params: escapeServiceOperationParams(loadOptions.customQueryParams),
                            expand: loadOptions.expand,
                            requireTotalCount: loadOptions.requireTotalCount
                        })
                },
                _insertImpl: function(values) {
                    this._requireKey();
                    var self = this,
                        d = $.Deferred();
                    $.when(this._sendRequest(this._url, "POST", null, values)).done(function(serverResponse) {
                        d.resolve(values, self.keyOf(serverResponse))
                    }).fail($.proxy(d.reject, d));
                    return d.promise()
                },
                _updateImpl: function(key, values) {
                    var d = $.Deferred();
                    $.when(this._sendRequest(this._byKeyUrl(key), "MERGE", null, values)).done(function() {
                        d.resolve(key, values)
                    }).fail($.proxy(d.reject, d));
                    return d.promise()
                },
                _removeImpl: function(key) {
                    var d = $.Deferred();
                    $.when(this._sendRequest(this._byKeyUrl(key), "DELETE")).done(function() {
                        d.resolve(key)
                    }).fail($.proxy(d.reject, d));
                    return d.promise()
                },
                _byKeyUrl: function(key) {
                    var keyType = this._keyType;
                    if ($.isPlainObject(keyType))
                        $.each(keyType, function(subKeyName, subKeyType) {
                            key[subKeyName] = convertSimpleKey(subKeyType, key[subKeyName])
                        });
                    else if (keyType)
                        key = convertSimpleKey(keyType, key);
                    return this._url + "(" + encodeURIComponent(odataUtils.serializeKey(key)) + ")"
                }
            }).include(SharedMethods);
        var ODataContext = Class.inherit({
                ctor: function(options) {
                    var self = this;
                    self._extractServiceOptions(options);
                    self._errorHandler = options.errorHandler;
                    $.each(options.entities || [], function(entityAlias, entityOptions) {
                        self[entityAlias] = new ODataStore($.extend({}, options, {url: self._url + "/" + encodeURIComponent(entityOptions.name || entityAlias)}, entityOptions))
                    })
                },
                get: function(operationName, params) {
                    return this.invoke(operationName, params, "GET")
                },
                invoke: function(operationName, params, httpMethod) {
                    httpMethod = httpMethod || "POST";
                    var d = $.Deferred();
                    $.when(this._sendRequest(this._url + "/" + encodeURIComponent(operationName), httpMethod, escapeServiceOperationParams(params))).done(function(r) {
                        if (r && operationName in r)
                            r = r[operationName];
                        d.resolve(r)
                    }).fail([this._errorHandler, data._handleError, $.proxy(d.reject, d)]);
                    return d.promise()
                },
                objectLink: function(entityAlias, key) {
                    var store = this[entityAlias];
                    if (!store)
                        throw Error("Unknown entity name or alias: " + entityAlias);
                    return {__metadata: {uri: store._byKeyUrl(key)}}
                }
            }).include(SharedMethods);
        $.extend(data, {
            ODataStore: ODataStore,
            ODataContext: ODataContext
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.store.rest.js */
    (function($, DX, undefined) {
        var data = DX.data;
        function createAjaxFailureHandler(deferred) {
            return function(xhr, textStatus) {
                    if (!xhr || !xhr.getResponseHeader)
                        deferred.reject.apply(deferred, arguments);
                    else
                        deferred.reject(Error(data.utils.errorMessageFromXhr(xhr, textStatus)))
                }
        }
        function operationCustomizerPropName(operationName) {
            return "_customize" + DX.inflector.camelize(operationName, true)
        }
        function pathPropName(operationName) {
            return "_" + operationName + "Path"
        }
        data.RestStore = data.Store.inherit({
            ctor: function(options) {
                DX.utils.logger.warn("RestStore is deprecated, use CustomStore instead");
                var self = this;
                self.callBase(options);
                options = options || {};
                self._url = String(options.url).replace(/\/+$/, "");
                self._jsonp = options.jsonp;
                self._withCredentials = options.withCredentials;
                $.each(["Load", "Insert", "Update", "Remove", "ByKey", "Operation"], function() {
                    var value = options["customize" + this];
                    if (value)
                        self[operationCustomizerPropName(this)] = value
                });
                $.each(["load", "insert", "update", "remove", "byKey"], function() {
                    var value = options[this + "Path"];
                    if (value)
                        self[pathPropName(this)] = value
                })
            },
            _loadImpl: function(options) {
                var d = $.Deferred(),
                    ajaxOptions = {
                        url: this._formatUrlNoKey("load"),
                        type: "GET"
                    };
                $.when(this._createAjax(ajaxOptions, "load", options)).done($.proxy(d.resolve, d)).fail(createAjaxFailureHandler(d));
                return this._addFailHandlers(d.promise())
            },
            createQuery: function() {
                throw Error("Not supported");
            },
            _insertImpl: function(values) {
                var d = $.Deferred(),
                    self = this,
                    ajaxOptions = {
                        url: this._formatUrlNoKey("insert"),
                        type: "POST",
                        contentType: "application/json",
                        data: JSON.stringify(values)
                    };
                $.when(this._createAjax(ajaxOptions, "insert")).done(function(serverResponse) {
                    d.resolve(values, self.key() && self.keyOf(serverResponse))
                }).fail(createAjaxFailureHandler(d));
                return d.promise()
            },
            _updateImpl: function(key, values) {
                var d = $.Deferred(),
                    ajaxOptions = {
                        url: this._formatUrlWithKey("update", key),
                        type: "PUT",
                        contentType: "application/json",
                        data: JSON.stringify(values)
                    };
                $.when(this._createAjax(ajaxOptions, "update")).done(function() {
                    d.resolve(key, values)
                }).fail(createAjaxFailureHandler(d));
                return d.promise()
            },
            _removeImpl: function(key) {
                var d = $.Deferred(),
                    ajaxOptions = {
                        url: this._formatUrlWithKey("remove", key),
                        type: "DELETE"
                    };
                $.when(this._createAjax(ajaxOptions, "remove")).done(function() {
                    d.resolve(key)
                }).fail(createAjaxFailureHandler(d));
                return d.promise()
            },
            _byKeyImpl: function(key) {
                var d = $.Deferred(),
                    ajaxOptions = {
                        url: this._formatUrlWithKey("byKey", key),
                        type: "GET"
                    };
                $.when(this._createAjax(ajaxOptions, "byKey")).done(function(data) {
                    d.resolve(data)
                }).fail(createAjaxFailureHandler(d));
                return d.promise()
            },
            _createAjax: function(ajaxOptions, operationName, extra) {
                var customizationFunc,
                    customizationResult;
                function isDeferred(obj) {
                    return "done" in obj && "fail" in obj
                }
                if (this._jsonp && ajaxOptions.type === "GET")
                    ajaxOptions.dataType = "jsonp";
                else
                    $.extend(true, ajaxOptions, {xhrFields: {withCredentials: this._withCredentials}});
                customizationFunc = this[operationCustomizerPropName("operation")];
                if (customizationFunc) {
                    customizationResult = customizationFunc(ajaxOptions, operationName, extra);
                    if (customizationResult) {
                        if (isDeferred(customizationResult))
                            return customizationResult;
                        ajaxOptions = customizationResult
                    }
                }
                customizationFunc = this[operationCustomizerPropName(operationName)];
                if (customizationFunc) {
                    customizationResult = customizationFunc(ajaxOptions, extra);
                    if (customizationResult) {
                        if (isDeferred(customizationResult))
                            return customizationResult;
                        ajaxOptions = customizationResult
                    }
                }
                return $.ajax(ajaxOptions)
            },
            _formatUrlNoKey: function(operationName) {
                var url = this._url,
                    path = this[pathPropName(operationName)];
                if (!path)
                    return url;
                if ($.isFunction(path))
                    return path(url);
                return url + "/" + path
            },
            _formatUrlWithKey: function(operationName, key) {
                var url = this._url,
                    path = this[pathPropName(operationName)];
                if (!path)
                    return url + "/" + encodeURIComponent(key);
                if ($.isFunction(path))
                    return path(url, key);
                return url + "/" + path + "/" + encodeURIComponent(key)
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file data.store.custom.js */
    (function($, DX, undefined) {
        var data = DX.data;
        var ERROR_QUERY_NOT_SUPPORTED = "CustomStore does not support creating queries",
            ERROR_MISSING_USER_FUNC = "Required option is not specified or is not a function: ",
            ERROR_INVALID_RETURN = "Invalid return value: ";
        var TOTAL_COUNT = "totalCount",
            LOAD = "load",
            BY_KEY = "byKey",
            INSERT = "insert",
            UPDATE = "update",
            REMOVE = "remove";
        function isPromise(obj) {
            return obj && $.isFunction(obj.done) && $.isFunction(obj.fail) && $.isFunction(obj.promise)
        }
        function trivialPromise(value) {
            return $.Deferred().resolve(value).promise()
        }
        function ensureRequiredFuncOption(name, obj) {
            if (!$.isFunction(obj))
                throw Error(ERROR_MISSING_USER_FUNC + name);
        }
        function throwInvalidUserFuncResult(name) {
            throw Error(ERROR_INVALID_RETURN + name);
        }
        function createUserFuncFailureHandler(pendingDeferred) {
            function errorMessageFromXhr(promiseArguments) {
                var xhr = promiseArguments[0],
                    textStatus = promiseArguments[1];
                if (!xhr || !xhr.getResponseHeader)
                    return null;
                return data.utils.errorMessageFromXhr(xhr, textStatus)
            }
            return function(arg) {
                    var error;
                    if (arg instanceof Error)
                        error = arg;
                    else
                        error = Error(errorMessageFromXhr(arguments) || arg && String(arg) || "Unknown error");
                    pendingDeferred.reject(error)
                }
        }
        data.CustomStore = data.Store.inherit({
            ctor: function(options) {
                options = options || {};
                this.callBase(options);
                this._useDefaultSearch = false;
                this._loadFunc = options[LOAD];
                this._totalCountFunc = options[TOTAL_COUNT];
                this._byKeyFunc = options[BY_KEY] || options.lookup;
                this._insertFunc = options[INSERT];
                this._updateFunc = options[UPDATE];
                this._removeFunc = options[REMOVE]
            },
            createQuery: function() {
                throw Error(ERROR_QUERY_NOT_SUPPORTED);
            },
            _totalCountImpl: function(options) {
                var userFunc = this._totalCountFunc,
                    userResult,
                    d = $.Deferred();
                ensureRequiredFuncOption(TOTAL_COUNT, userFunc);
                userResult = userFunc(options);
                if (!isPromise(userResult)) {
                    userResult = Number(userResult);
                    if (!isFinite(userResult))
                        throwInvalidUserFuncResult(TOTAL_COUNT);
                    userResult = trivialPromise(userResult)
                }
                userResult.done(function(count) {
                    d.resolve(Number(count))
                }).fail(createUserFuncFailureHandler(d));
                return d.promise()
            },
            _loadImpl: function(options) {
                var userFunc = this._loadFunc,
                    userResult,
                    d = $.Deferred();
                ensureRequiredFuncOption(LOAD, userFunc);
                userResult = userFunc(options);
                if ($.isArray(userResult))
                    userResult = trivialPromise(userResult);
                else if (userResult === null || userResult === undefined)
                    userResult = trivialPromise([]);
                else if (!isPromise(userResult))
                    throwInvalidUserFuncResult(LOAD);
                userResult.done(function(data, extra) {
                    d.resolve(data, extra)
                }).fail(createUserFuncFailureHandler(d));
                return this._addFailHandlers(d.promise())
            },
            _byKeyImpl: function(key) {
                var userFunc = this._byKeyFunc,
                    userResult,
                    d = $.Deferred();
                ensureRequiredFuncOption(BY_KEY, userFunc);
                userResult = userFunc(key);
                if (!isPromise(userResult))
                    userResult = trivialPromise(userResult);
                userResult.done(function(obj) {
                    d.resolve(obj)
                }).fail(createUserFuncFailureHandler(d));
                return d.promise()
            },
            _insertImpl: function(values) {
                var userFunc = this._insertFunc,
                    userResult,
                    d = $.Deferred();
                ensureRequiredFuncOption(INSERT, userFunc);
                userResult = userFunc(values);
                if (!isPromise(userResult))
                    userResult = trivialPromise(userResult);
                userResult.done(function(newKey) {
                    d.resolve(values, newKey)
                }).fail(createUserFuncFailureHandler(d));
                return d.promise()
            },
            _updateImpl: function(key, values) {
                var userFunc = this._updateFunc,
                    userResult,
                    d = $.Deferred();
                ensureRequiredFuncOption(UPDATE, userFunc);
                userResult = userFunc(key, values);
                if (!isPromise(userResult))
                    userResult = trivialPromise();
                userResult.done(function() {
                    d.resolve(key, values)
                }).fail(createUserFuncFailureHandler(d));
                return d.promise()
            },
            _removeImpl: function(key) {
                var userFunc = this._removeFunc,
                    userResult,
                    d = $.Deferred();
                ensureRequiredFuncOption(REMOVE, userFunc);
                userResult = userFunc(key);
                if (!isPromise(userResult))
                    userResult = trivialPromise();
                userResult.done(function() {
                    d.resolve(key)
                }).fail(createUserFuncFailureHandler(d));
                return d.promise()
            }
        });
        data.CustomStore_internals = {ERRORS: {
                QUERY_NOT_SUPPORTED: ERROR_QUERY_NOT_SUPPORTED,
                MISSING_USER_FUNC: ERROR_MISSING_USER_FUNC,
                INVALID_RETURN: ERROR_INVALID_RETURN
            }}
    })(jQuery, DevExpress);
    /*! Module core, file data.dataSource.js */
    (function($, DX, undefined) {
        var data = DX.data,
            CustomStore = data.CustomStore,
            Class = DX.Class;
        var storeTypeRegistry = {
                jaydata: "JayDataStore",
                breeze: "BreezeStore",
                odata: "ODataStore",
                local: "LocalStore",
                array: "ArrayStore"
            };
        function normalizeDataSourceOptions(options) {
            var store;
            function createCustomStoreFromLoadFunc() {
                var storeConfig = {};
                $.each(["load", "byKey", "lookup", "totalCount", "insert", "update", "remove"], function() {
                    storeConfig[this] = options[this];
                    delete options[this]
                });
                return new CustomStore(storeConfig)
            }
            function createStoreFromConfig(storeConfig) {
                var storeCtor = data[storeTypeRegistry[storeConfig.type]];
                delete storeConfig.type;
                return new storeCtor(storeConfig)
            }
            function createCustomStoreFromUrl(url) {
                return new CustomStore({load: function() {
                            return $.getJSON(url)
                        }})
            }
            if (typeof options === "string")
                options = createCustomStoreFromUrl(options);
            if (options === undefined)
                options = [];
            if ($.isArray(options) || options instanceof data.Store)
                options = {store: options};
            else
                options = $.extend({}, options);
            store = options.store;
            if ("load" in options)
                store = createCustomStoreFromLoadFunc();
            else if ($.isArray(store))
                store = new data.ArrayStore(store);
            else if ($.isPlainObject(store))
                store = createStoreFromConfig($.extend({}, store));
            options.store = store;
            return options
        }
        function generateStoreLoadOptionAccessor(optionName) {
            return function(expr) {
                    var argc = arguments.length;
                    if (argc) {
                        if (argc > 1)
                            expr = $.makeArray(arguments);
                        this._storeLoadOptions[optionName] = expr
                    }
                    return this._storeLoadOptions[optionName]
                }
        }
        function addOldUserDataSourceBackwardCompatibilityOptions(dataSource, storeLoadOptions) {
            storeLoadOptions.refresh = !dataSource._paginate || dataSource._pageIndex === 0;
            if (storeLoadOptions.searchValue !== null)
                storeLoadOptions.searchString = storeLoadOptions.searchValue
        }
        var DataSource = Class.inherit({
                ctor: function(options) {
                    options = normalizeDataSourceOptions(options);
                    this._store = options.store;
                    this._storeLoadOptions = this._extractLoadOptions(options);
                    this._mapFunc = options.map;
                    this._postProcessFunc = options.postProcess;
                    this._pageIndex = 0;
                    this._pageSize = options.pageSize !== undefined ? options.pageSize : 20;
                    this._items = [];
                    this._totalCount = -1;
                    this._isLoaded = false;
                    this._loadingCount = 0;
                    this._preferSync = options._preferSync;
                    this._loadQueue = this._createLoadQueue();
                    this._searchValue = "searchValue" in options ? options.searchValue : null;
                    this._searchOperation = options.searchOperation || "contains";
                    this._searchExpr = options.searchExpr;
                    this._paginate = options.paginate;
                    if (this._paginate === undefined)
                        this._paginate = !this.group();
                    this._isLastPage = !this._paginate;
                    this._userData = {};
                    this.changed = $.Callbacks();
                    this.loadError = $.Callbacks();
                    this.loadingChanged = $.Callbacks()
                },
                dispose: function() {
                    this.changed.empty();
                    this.loadError.empty();
                    this.loadingChanged.empty();
                    delete this._store;
                    this._disposed = true
                },
                _extractLoadOptions: function(options) {
                    var result = {},
                        names = ["sort", "filter", "select", "group", "requireTotalCount"],
                        customNames = this._store._customLoadOptions();
                    if (customNames)
                        names = names.concat(customNames);
                    $.each(names, function() {
                        result[this] = options[this]
                    });
                    return result
                },
                loadOptions: function() {
                    return this._storeLoadOptions
                },
                items: function() {
                    return this._items
                },
                pageIndex: function(newIndex) {
                    if (newIndex !== undefined) {
                        this._pageIndex = newIndex;
                        this._isLastPage = !this._paginate
                    }
                    return this._pageIndex
                },
                isLastPage: function() {
                    return this._isLastPage
                },
                sort: generateStoreLoadOptionAccessor("sort"),
                filter: generateStoreLoadOptionAccessor("filter"),
                group: generateStoreLoadOptionAccessor("group"),
                select: generateStoreLoadOptionAccessor("select"),
                searchValue: function(value) {
                    if (value !== undefined)
                        this._searchValue = value;
                    return this._searchValue
                },
                searchOperation: function(op) {
                    if (op !== undefined)
                        this._searchOperation = op;
                    return this._searchOperation
                },
                searchExpr: function(expr) {
                    var argc = arguments.length;
                    if (argc) {
                        if (argc > 1)
                            expr = $.makeArray(arguments);
                        this._searchExpr = expr
                    }
                    return this._searchExpr
                },
                store: function() {
                    return this._store
                },
                key: function() {
                    return this._store && this._store.key()
                },
                totalCount: function() {
                    return this._totalCount
                },
                isLoaded: function() {
                    return this._isLoaded
                },
                isLoading: function() {
                    return this._loadingCount > 0
                },
                _createLoadQueue: function() {
                    return DX.createQueue()
                },
                _changeLoadingCount: function(increment) {
                    var oldLoading = this.isLoading(),
                        newLoading;
                    this._loadingCount += increment;
                    newLoading = this.isLoading();
                    if (oldLoading ^ newLoading)
                        this.loadingChanged.fire(newLoading)
                },
                _scheduleLoadCallbacks: function(deferred) {
                    var thisSource = this;
                    thisSource._changeLoadingCount(1);
                    deferred.always(function() {
                        thisSource._changeLoadingCount(-1)
                    })
                },
                _scheduleChangedCallbacks: function(deferred) {
                    var self = this;
                    deferred.done(function() {
                        self.changed.fire()
                    })
                },
                load: function() {
                    var thisSource = this,
                        d = $.Deferred(),
                        errorCallback = this.loadError,
                        storeLoadOptions;
                    this._scheduleLoadCallbacks(d);
                    this._scheduleChangedCallbacks(d);
                    storeLoadOptions = this._createStoreLoadOptions();
                    function loadTask() {
                        if (thisSource._disposed)
                            return undefined;
                        return thisSource._loadFromStore(storeLoadOptions, d)
                    }
                    this._loadQueue.add(function() {
                        loadTask();
                        return d.promise()
                    }, function() {
                        thisSource._changeLoadingCount(-1)
                    });
                    return d.promise().fail($.proxy(errorCallback.fire, errorCallback))
                },
                _addSearchOptions: function(storeLoadOptions) {
                    if (this._disposed)
                        return;
                    if (this.store()._useDefaultSearch)
                        this._addSearchFilter(storeLoadOptions);
                    else {
                        storeLoadOptions.searchValue = this._searchValue;
                        storeLoadOptions.searchExpr = this._searchExpr
                    }
                },
                _createStoreLoadOptions: function() {
                    var result = $.extend({}, this._storeLoadOptions);
                    this._addSearchOptions(result);
                    if (this._paginate) {
                        result.pageIndex = this._pageIndex;
                        if (this._pageSize) {
                            result.skip = this._pageIndex * this._pageSize;
                            result.take = this._pageSize
                        }
                    }
                    result.userData = this._userData;
                    addOldUserDataSourceBackwardCompatibilityOptions(this, result);
                    return result
                },
                _addSearchFilter: function(storeLoadOptions) {
                    var value = this._searchValue,
                        op = this._searchOperation,
                        selector = this._searchExpr,
                        searchFilter = [];
                    if (!value)
                        return;
                    if (!selector)
                        selector = "this";
                    if (!$.isArray(selector))
                        selector = [selector];
                    $.each(selector, function(i, item) {
                        if (searchFilter.length)
                            searchFilter.push("or");
                        searchFilter.push([item, op, value])
                    });
                    if (storeLoadOptions.filter)
                        storeLoadOptions.filter = [searchFilter, storeLoadOptions.filter];
                    else
                        storeLoadOptions.filter = searchFilter
                },
                _loadFromStore: function(storeLoadOptions, pendingDeferred) {
                    var thisSource = this;
                    function handleSuccess(data, extra) {
                        function processResult() {
                            thisSource._processStoreLoadResult(data, extra, storeLoadOptions, pendingDeferred)
                        }
                        if (thisSource._preferSync)
                            processResult();
                        else
                            DX.utils.executeAsync(processResult)
                    }
                    return this.store().load(storeLoadOptions).done(handleSuccess).fail($.proxy(pendingDeferred.reject, pendingDeferred))
                },
                _processStoreLoadResult: function(data, extra, storeLoadOptions, pendingDeferred) {
                    var thisSource = this;
                    function resolvePendingDeferred() {
                        thisSource._isLoaded = true;
                        thisSource._totalCount = isFinite(extra.totalCount) ? extra.totalCount : -1;
                        return pendingDeferred.resolve(data, extra)
                    }
                    function proceedLoadingTotalCount() {
                        thisSource.store().totalCount(storeLoadOptions).done(function(count) {
                            extra.totalCount = count;
                            resolvePendingDeferred()
                        }).fail(function(){})
                    }
                    if (thisSource._disposed)
                        return;
                    data = thisSource._transformLoadedData(data);
                    if (!$.isPlainObject(extra))
                        extra = {};
                    thisSource._items = data;
                    if (!data.length || !thisSource._paginate || thisSource._pageSize && data.length < thisSource._pageSize)
                        thisSource._isLastPage = true;
                    if (storeLoadOptions.requireTotalCount && !isFinite(extra.totalCount))
                        proceedLoadingTotalCount();
                    else
                        resolvePendingDeferred()
                },
                _transformLoadedData: function(data) {
                    var result = $.makeArray(data);
                    if (this._mapFunc)
                        result = $.map(result, this._mapFunc);
                    if (this._postProcessFunc)
                        result = this._postProcessFunc(result);
                    return result
                }
            });
        data.Store.redefine({toDataSource: function(options) {
                DX.utils.logger.warn("toDataSource() method is deprecated, use 'new DevExpress.data.DataSource(...)' instead");
                return new DataSource($.extend({store: this}, options))
            }});
        $.extend(true, data, {
            DataSource: DataSource,
            createDataSource: function(options) {
                DX.utils.logger.warn("createDataSource() method is deprecated, use 'new DevExpress.data.DataSource(...)' instead");
                return new DataSource(options)
            },
            utils: {
                storeTypeRegistry: storeTypeRegistry,
                normalizeDataSourceOptions: normalizeDataSourceOptions
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file social.js */
    DevExpress.social = {};
    /*! Module core, file facebook.js */
    (function($, DX, undefined) {
        function notifyDeprecated() {
            DX.utils.logger.warn("DevExpress.social API is deprecated. Use official Facebook library instead")
        }
        var social = DX.social;
        var location = window.location,
            navigator = window.navigator,
            encodeURIComponent = window.encodeURIComponent,
            decodeURIComponent = window.decodeURIComponent,
            iosStandaloneMode = navigator.standalone,
            cordovaMode = false;
        if (window.cordova)
            $(document).on("deviceready", function() {
                cordovaMode = true
            });
        var ACCESS_TOKEN_KEY = "dx-facebook-access-token",
            IOS_STANDALONE_STEP1_KEY = "dx-facebook-step1",
            IOS_STANDALONE_STEP2_KEY = "dx-facebook-step2";
        var accessToken = null,
            expires = null,
            connectionChanged = $.Callbacks();
        var pendingLoginRedirectUrl;
        var isConnected = function() {
                return !!accessToken
            };
        var getAccessTokenObject = function() {
                return {
                        accessToken: accessToken,
                        expiresIn: accessToken ? expires : 0
                    }
            };
        var FB = social.Facebook = {
                loginRedirectUrl: "FacebookLoginCallback.html",
                connectionChanged: connectionChanged,
                isConnected: isConnected,
                getAccessTokenObject: getAccessTokenObject,
                jsonp: false
            };
        var login = function(appId, options) {
                notifyDeprecated();
                options = options || {};
                if (cordovaMode)
                    pendingLoginRedirectUrl = "https://www.facebook.com/connect/login_success.html";
                else
                    pendingLoginRedirectUrl = formatLoginRedirectUrl();
                var scope = (options.permissions || []).join(),
                    url = "https://www.facebook.com/dialog/oauth?display=popup&client_id=" + appId + "&redirect_uri=" + encodeURIComponent(pendingLoginRedirectUrl) + "&scope=" + encodeURIComponent(scope) + "&response_type=token";
                if (iosStandaloneMode)
                    putData(IOS_STANDALONE_STEP1_KEY, location.href);
                if (cordovaMode)
                    startLogin_cordova(url);
                else
                    startLogin_browser(url)
            };
        var formatLoginRedirectUrl = function() {
                var pathSegments = location.pathname.split(/\//g);
                pathSegments.pop();
                pathSegments.push(FB.loginRedirectUrl);
                return location.protocol + "//" + location.host + pathSegments.join("/")
            };
        var startLogin_browser = function(loginUrl) {
                var width = 512,
                    height = 320,
                    left = (screen.width - width) / 2,
                    top = (screen.height - height) / 2;
                window.open(loginUrl, null, "width=" + width + ",height=" + height + ",toolbar=0,scrollbars=0,status=0,resizable=0,menuBar=0,left=" + left + ",top=" + top)
            };
        var startLogin_cordova = function(loginUrl) {
                var ref = window.open(loginUrl, "_blank");
                ref.addEventListener('exit', function(event) {
                    pendingLoginRedirectUrl = null
                });
                ref.addEventListener('loadstop', function(event) {
                    var url = unescape(event.url);
                    if (url.indexOf(pendingLoginRedirectUrl) === 0) {
                        ref.close();
                        _processLoginRedirectUrl(url)
                    }
                })
            };
        var handleLoginRedirect = function() {
                var opener = window.opener;
                if (iosStandaloneMode) {
                    putData(IOS_STANDALONE_STEP2_KEY, location.href);
                    location.href = getData(IOS_STANDALONE_STEP1_KEY)
                }
                else if (opener && opener.DevExpress) {
                    opener.DevExpress.social.Facebook._processLoginRedirectUrl(location.href);
                    window.close()
                }
            };
        var _processLoginRedirectUrl = function(url) {
                var params = parseUrlFragment(url);
                expires = params.expires_in;
                changeToken(params.access_token);
                pendingLoginRedirectUrl = null
            };
        var parseUrlFragment = function(url) {
                var hash = url.split("#")[1];
                if (!hash)
                    return {};
                var pairs = hash.split(/&/g),
                    result = {};
                $.each(pairs, function(i) {
                    var splitPair = this.split("=");
                    result[splitPair[0]] = decodeURIComponent(splitPair[1])
                });
                return result
            };
        var logout = function() {
                notifyDeprecated();
                changeToken(null)
            };
        var changeToken = function(value) {
                if (value === accessToken)
                    return;
                accessToken = value;
                putData(ACCESS_TOKEN_KEY, value);
                connectionChanged.fire(!!value)
            };
        var api = function(resource, method, params) {
                notifyDeprecated();
                if (!isConnected())
                    throw Error("Not connected");
                if (typeof method !== "string") {
                    params = method;
                    method = undefined
                }
                method = (method || "get").toLowerCase();
                var d = $.Deferred();
                var args = arguments;
                $.ajax({
                    url: "https://graph.facebook.com/" + resource,
                    type: method,
                    data: $.extend({access_token: accessToken}, params),
                    dataType: FB.jsonp && method === "get" ? "jsonp" : "json"
                }).done(function(response) {
                    response = response || simulateErrorResponse();
                    if (response.error)
                        d.reject(response.error);
                    else
                        d.resolve(response)
                }).fail(function(xhr) {
                    var response;
                    try {
                        response = $.parseJSON(xhr.responseText);
                        var tries = args[3] || 0;
                        if (tries++ < 3 && response.error.code == 190 && response.error.error_subcode == 466) {
                            setTimeout(function() {
                                api(resource, method, params, tries).done(function(result) {
                                    d.resolve(result)
                                }).fail(function(error) {
                                    d.reject(error)
                                })
                            }, 500);
                            return
                        }
                    }
                    catch(x) {
                        response = simulateErrorResponse()
                    }
                    d.reject(response.error)
                });
                return d.promise()
            };
        var simulateErrorResponse = function() {
                return {error: {message: "Unknown error"}}
            };
        var ensureStorageBackend = function() {
                if (!hasStorageBackend())
                    throw Error("HTML5 sessionStorage or jQuery.cookie plugin is required");
            };
        var hasStorageBackend = function() {
                return !!($.cookie || window.sessionStorage)
            };
        var putData = function(key, data) {
                ensureStorageBackend();
                data = JSON.stringify(data);
                if (window.sessionStorage)
                    if (data === null)
                        sess.removeItem(key);
                    else
                        sessionStorage.setItem(key, data);
                else
                    $.cookie(key, data)
            };
        var getData = function(key) {
                ensureStorageBackend();
                try {
                    return JSON.parse(window.sessionStorage ? sessionStorage.getItem(key) : $.cookie(key))
                }
                catch(x) {
                    return null
                }
            };
        if (hasStorageBackend())
            accessToken = getData(ACCESS_TOKEN_KEY);
        if (iosStandaloneMode) {
            var url = getData(IOS_STANDALONE_STEP2_KEY);
            if (url) {
                _processLoginRedirectUrl(url);
                putData(IOS_STANDALONE_STEP1_KEY, null);
                putData(IOS_STANDALONE_STEP2_KEY, null)
            }
        }
        $.extend(FB, {
            login: login,
            logout: logout,
            handleLoginRedirect: handleLoginRedirect,
            _processLoginRedirectUrl: _processLoginRedirectUrl,
            api: api
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.js */
    (function($, DX, undefined) {
        var ui = DX.ui = {};
        var initViewport = function(options) {
                options = $.extend({}, options);
                var device = DX.devices.real;
                var allowZoom = options.allowZoom,
                    allowPan = options.allowPan;
                DX.overlayTargetContainer(".dx-viewport");
                var metaSelector = "meta[name=viewport]";
                if (!$(metaSelector).length)
                    $("<meta />").attr("name", "viewport").appendTo("head");
                var metaVerbs = ["width=device-width"],
                    msTouchVerbs = [];
                if (allowZoom)
                    msTouchVerbs.push("pinch-zoom");
                else
                    metaVerbs.push("initial-scale=1.0", "maximum-scale=1.0");
                if (allowPan)
                    msTouchVerbs.push("pan-x", "pan-y");
                if (!allowPan && !allowZoom)
                    $("html, body").css("overflow", "hidden");
                else
                    $("html").css("-ms-overflow-style", "-ms-autohiding-scrollbar");
                $(metaSelector).attr("content", metaVerbs.join());
                $("html").css("-ms-touch-action", msTouchVerbs.join(" ") || "none");
                if (DX.support.touch)
                    $(document).off(".dxInitViewport").on("touchmove.dxInitViewport", function(e) {
                        var count = e.originalEvent.touches.length,
                            zoomDisabled = !allowZoom && count > 1,
                            panDisabled = !allowPan && count === 1 && !e.isScrollingEvent;
                        if (zoomDisabled || panDisabled)
                            e.preventDefault()
                    });
                if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
                    $(document.head).append($("<style/>").text("@-ms-viewport{ width: auto!important; user-zoom: fixed; max-zoom: 1; min-zoom: 1; }"));
                    $(window).bind("load resize", function(e) {
                        var TOP_BAR_W = 44,
                            TOP_BAR_H = 21,
                            ADDRESS_BAR_H = 72;
                        var isStandalone = 'Notify' in window.external;
                        var barWidth = isStandalone ? TOP_BAR_W : 0,
                            barHeight = isStandalone ? TOP_BAR_H : ADDRESS_BAR_H;
                        var actualHeight = $(window).width() < $(window).height() ? Math.round(screen.availHeight * (document.body.clientWidth / screen.availWidth)) - barHeight : Math.round(screen.availWidth * (document.body.clientHeight / screen.availHeight)) - barWidth;
                        document.body.style.setProperty("min-height", actualHeight + "px", "important")
                    })
                }
            };
        var TemplateProvider = DX.Class.inherit({
                getTemplateClass: function() {
                    return Template
                },
                supportDefaultTemplate: function() {
                    return false
                },
                getDefaultTemplate: function() {
                    return null
                }
            });
        var Template = DX.Class.inherit({
                ctor: function(element) {
                    this._template = this._element = $(element).detach()
                },
                render: function(container) {
                    var renderedTemplate = this._template.clone();
                    container.append(renderedTemplate);
                    return renderedTemplate
                },
                dispose: $.noop
            });
        DX.registerActionExecutor({
            designMode: {validate: function(e) {
                    if (DX.designMode)
                        e.canceled = true
                }},
            gesture: {validate: function(e) {
                    if (!e.args.length)
                        return;
                    var args = e.args[0],
                        element = args.itemElement || args.element;
                    while (element && element.length) {
                        if (element.data("dxGesture")) {
                            e.canceled = true;
                            break
                        }
                        element = element.parent()
                    }
                }},
            disabled: {validate: function(e) {
                    if (!e.args.length)
                        return;
                    var args = e.args[0],
                        element = args.itemElement || args.element;
                    if (element && element.is(".dx-state-disabled, .dx-state-disabled *"))
                        e.canceled = true
                }}
        });
        $.extend(ui, {
            TemplateProvider: TemplateProvider,
            Template: Template,
            initViewport: initViewport
        });
        ui.__internals = {Template: Template}
    })(jQuery, DevExpress);
    /*! Module core, file ui.dialog.js */
    (function($, DX, undefined) {
        var ui = DX.ui;
        var DEFAULT_BUTTON = {
                text: "Ok",
                clickAction: function() {
                    return true
                }
            };
        var DX_DIALOG_CLASSNAME = "dx-dialog",
            DX_DIALOG_WRAPPER_CLASSNAME = DX_DIALOG_CLASSNAME + "-wrapper",
            DX_DIALOG_ROOT_CLASSNAME = DX_DIALOG_CLASSNAME + "-root",
            DX_DIALOG_CONTENT_CLASSNAME = DX_DIALOG_CLASSNAME + "-content",
            DX_DIALOG_MESSAGE_CLASSNAME = DX_DIALOG_CLASSNAME + "-message",
            DX_DIALOG_BUTTONS_CLASSNAME = DX_DIALOG_CLASSNAME + "-buttons",
            DX_DIALOG_BUTTON_CLASSNAME = DX_DIALOG_CLASSNAME + "-button";
        var dialog = function(options) {
                var self = this,
                    result;
                if (!ui.dxPopup)
                    throw new Error("DevExpress.ui.dxPopup required");
                var deferred = $.Deferred();
                options = $.extend(ui.optionsByDevice(DX.devices.current(), "dxDialog"), options);
                var $holder = $(".dx-viewport");
                var $element = $("<div/>").addClass(DX_DIALOG_CLASSNAME).appendTo($holder);
                var $message = $("<div/>").addClass(DX_DIALOG_MESSAGE_CLASSNAME).html(String(options.message));
                var $buttons = $("<div/>").addClass(DX_DIALOG_BUTTONS_CLASSNAME);
                var popupInstance = $element.dxPopup({
                        title: options.title || self.title,
                        height: "auto",
                        width: function() {
                            var isPortrait = $(window).height() > $(window).width(),
                                key = (isPortrait ? "p" : "l") + "Width";
                            return options.hasOwnProperty(key) ? options[key] : options["width"]
                        },
                        contentReadyAction: function() {
                            popupInstance.content().addClass(DX_DIALOG_CONTENT_CLASSNAME).append($message).append($buttons)
                        },
                        animation: {
                            show: {
                                type: "pop",
                                duration: 400
                            },
                            hide: {
                                type: "pop",
                                duration: 400,
                                to: {
                                    opacity: 0,
                                    scale: 0
                                },
                                from: {
                                    opacity: 1,
                                    scale: 1
                                }
                            }
                        }
                    }).data("dxPopup");
                popupInstance._wrapper().addClass(DX_DIALOG_WRAPPER_CLASSNAME);
                $.each(options.buttons || [DEFAULT_BUTTON], function() {
                    var button = $("<div/>").addClass(DX_DIALOG_BUTTON_CLASSNAME).appendTo($buttons);
                    var action = new DX.Action(this.clickAction, {context: popupInstance});
                    button.dxButton($.extend(this, {clickAction: function() {
                            result = action.execute(arguments);
                            hide()
                        }}))
                });
                popupInstance._wrapper().addClass(DX_DIALOG_ROOT_CLASSNAME);
                function show() {
                    popupInstance.show();
                    return deferred.promise()
                }
                function hide(value) {
                    popupInstance.hide().done(function() {
                        popupInstance._element().remove()
                    });
                    deferred.resolve(result || value)
                }
                return {
                        show: show,
                        hide: hide
                    }
            };
        var alert = function(message, title) {
                var dialogInstance,
                    options = $.isPlainObject(message) ? message : {
                        title: title,
                        message: message
                    };
                dialogInstance = ui.dialog.custom(options);
                return dialogInstance.show()
            };
        var confirm = function(message, title) {
                var dialogInstance,
                    options = $.isPlainObject(message) ? message : {
                        title: title,
                        message: message,
                        buttons: [{
                                text: Globalize.localize("Yes"),
                                clickAction: function() {
                                    return true
                                }
                            }, {
                                text: Globalize.localize("No"),
                                clickAction: function() {
                                    return false
                                }
                            }]
                    };
                dialogInstance = ui.dialog.custom(options);
                return dialogInstance.show()
            };
        var notify = function(message, type, displayTime) {
                var options,
                    instance;
                options = $.isPlainObject(message) ? message : {message: message};
                if (!ui.dxToast) {
                    alert(options.message);
                    return
                }
                if (type)
                    options.type = type;
                if (displayTime)
                    options.displayTime = displayTime;
                instance = $("<div/>").appendTo(".dx-viewport").addClass("dx-static").dxToast(options).data("dxToast");
                instance.option("hiddenAction", function(args) {
                    args.element.remove();
                    new DX.Action(options.hiddenAction, {context: args.model}).execute(arguments)
                });
                instance.show()
            };
        $.extend(ui, {
            notify: notify,
            dialog: {
                custom: dialog,
                alert: alert,
                confirm: confirm
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.dataHelper.js */
    (function($, DX, undefined) {
        var data = DX.data;
        var DATA_SOURCE_OPTIONS_METHOD = "_dataSourceOptions",
            DATA_SOURCE_CHANGED_METHOD = "_handleDataSourceChanged",
            DATA_SOURCE_LOAD_ERROR_METHOD = "_handleDataSourceLoadError",
            DATA_SOURCE_LOADING_CHANGED_METHOD = "_handleDataSourceLoadingChanged";
        DX.ui.DataHelperMixin = {
            ctor: function() {
                this.disposing.add(function() {
                    this._disposeDataSource()
                })
            },
            _refreshDataSource: function() {
                this._initDataSource();
                this._loadDataSource()
            },
            _initDataSource: function() {
                var dataSourceOptions = this.option("dataSource"),
                    widgetDataSourceOptions,
                    dataSourceType;
                this._disposeDataSource();
                if (dataSourceOptions) {
                    if (dataSourceOptions instanceof data.DataSource) {
                        this._isSharedDataSource = true;
                        this._dataSource = dataSourceOptions
                    }
                    else {
                        widgetDataSourceOptions = DATA_SOURCE_OPTIONS_METHOD in this ? this[DATA_SOURCE_OPTIONS_METHOD]() : {};
                        dataSourceType = this._dataSourceType ? this._dataSourceType() : data.DataSource;
                        this._dataSource = new dataSourceType($.extend(true, {}, widgetDataSourceOptions, data.utils.normalizeDataSourceOptions(dataSourceOptions)))
                    }
                    this._addDataSourceHandlers()
                }
            },
            _addDataSourceHandlers: function() {
                if (DATA_SOURCE_CHANGED_METHOD in this)
                    this._addDataSourceChangeHandler();
                if (DATA_SOURCE_LOAD_ERROR_METHOD in this)
                    this._addDataSourceLoadErrorHandler();
                if (DATA_SOURCE_LOADING_CHANGED_METHOD in this)
                    this._addDataSourceLoadingChangedHandler()
            },
            _addDataSourceChangeHandler: function() {
                var self = this,
                    dataSource = this._dataSource;
                this._dataSourceChangedHandler = function() {
                    self[DATA_SOURCE_CHANGED_METHOD](dataSource.items())
                };
                dataSource.changed.add(this._dataSourceChangedHandler)
            },
            _addDataSourceLoadErrorHandler: function() {
                this._dataSourceLoadErrorHandler = $.proxy(this[DATA_SOURCE_LOAD_ERROR_METHOD], this);
                this._dataSource.loadError.add(this._dataSourceLoadErrorHandler)
            },
            _addDataSourceLoadingChangedHandler: function() {
                this._dataSourceLoadingChangedHandler = $.proxy(this[DATA_SOURCE_LOADING_CHANGED_METHOD], this);
                this._dataSource.loadingChanged.add(this._dataSourceLoadingChangedHandler)
            },
            _loadDataSource: function() {
                if (this._dataSource) {
                    var dataSource = this._dataSource;
                    if (dataSource.isLoaded())
                        this._dataSourceChangedHandler();
                    else
                        dataSource.load()
                }
            },
            _disposeDataSource: function() {
                if (this._dataSource) {
                    if (this._isSharedDataSource) {
                        delete this._isSharedDataSource;
                        this._dataSource.changed.remove(this._dataSourceChangedHandler);
                        this._dataSource.loadError.remove(this._dataSourceLoadErrorHandler);
                        this._dataSource.loadingChanged.remove(this._dataSourceLoadingChangedHandler)
                    }
                    else
                        this._dataSource.dispose();
                    delete this._dataSource;
                    delete this._dataSourceChangedHandler;
                    delete this._dataSourceLoadErrorHandler;
                    delete this._dataSourceLoadingChangedHandler
                }
            }
        }
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            EVENT_SOURCES_REGEX = {
                mouse: /^mouse/i,
                touch: /^touch/i,
                keyboard: /^key/i,
                pointer: /pointer/i
            };
        var eventSource = function(e) {
                var result = "other";
                $.each(EVENT_SOURCES_REGEX, function(key) {
                    if (this.test(e.type)) {
                        result = key;
                        return false
                    }
                });
                return result
            };
        var isPointerEvent = function(e) {
                return eventSource(e) === "pointer"
            };
        var isMouseEvent = function(e) {
                return eventSource(e) === "mouse" || isPointerEvent(e) && e.pointerType === "mouse"
            };
        var isTouchEvent = function(e) {
                return eventSource(e) === "touch" || isPointerEvent(e) && e.pointerType === "touch"
            };
        var isKeyboardEvent = function(e) {
                return eventSource(e) === "keyboard"
            };
        var addNamespace = function(eventNames, namespace) {
                if (!namespace)
                    throw Error("Namespace is not defined");
                if (typeof eventNames === "string")
                    return addNamespace(eventNames.split(/\s+/g), namespace);
                $.each(eventNames, function(index, eventName) {
                    eventNames[index] = eventName + "." + namespace
                });
                return eventNames.join(" ")
            };
        var eventData = function(e) {
                if (isPointerEvent(e) && isTouchEvent(e)) {
                    var touch = (e.originalEvent.originalEvent || e.originalEvent).changedTouches[0];
                    return {
                            x: touch.pageX,
                            y: touch.pageY,
                            time: e.timeStamp
                        }
                }
                if (isMouseEvent(e))
                    return {
                            x: e.pageX,
                            y: e.pageY,
                            time: e.timeStamp
                        };
                if (isTouchEvent(e)) {
                    var touch = (e.changedTouches || e.originalEvent.changedTouches)[0];
                    return {
                            x: touch.pageX,
                            y: touch.pageY,
                            time: e.timeStamp
                        }
                }
            };
        var eventDelta = function(from, to) {
                return {
                        x: to.x - from.x,
                        y: to.y - from.y,
                        time: to.time - from.time || 1
                    }
            };
        var hasTouches = function(e) {
                if (isMouseEvent(e) || isPointerEvent(e))
                    return 0;
                if (isTouchEvent(e))
                    return e.originalEvent.touches.length
            };
        var needSkipEvent = function(e) {
                if (isMouseEvent(e))
                    return $(e.target).is("input, textarea, select") || e.which > 1;
                if (isTouchEvent(e))
                    return (e.originalEvent.changedTouches || e.originalEvent.originalEvent.changedTouches).length !== 1
            };
        var createEvent = function(sourceEvent, props) {
                var event = $.Event(sourceEvent, props),
                    originalEvent = event.originalEvent,
                    propNames = $.event.props.slice();
                if (isMouseEvent(sourceEvent) || isTouchEvent(sourceEvent))
                    $.merge(propNames, $.event.mouseHooks.props);
                if (isKeyboardEvent(sourceEvent))
                    $.merge(propNames, $.event.keyHooks.props);
                if (originalEvent)
                    $.each(propNames, function() {
                        event[this] = originalEvent[this]
                    });
                return event
            };
        var fireEvent = function(props) {
                var event = createEvent(props.originalEvent, props);
                $.event.trigger(event, null, props.target || event.target);
                return event
            };
        ui.events = {
            eventSource: eventSource,
            isPointerEvent: isPointerEvent,
            isMouseEvent: isMouseEvent,
            isTouchEvent: isTouchEvent,
            isKeyboardEvent: isKeyboardEvent,
            addNamespace: addNamespace,
            hasTouches: hasTouches,
            eventData: eventData,
            eventDelta: eventDelta,
            needSkipEvent: needSkipEvent,
            createEvent: createEvent,
            fireEvent: fireEvent
        }
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.pointer.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            support = DX.support,
            device = DX.devices.real,
            events = ui.events,
            eventNS = $.event,
            specialNS = eventNS.special,
            MOUSE_EVENT_LOCK_TIMEOUT = 100,
            mouseLocked = false,
            unlockMouseTimer = null;
        var POINTER_EVENTS_NAMESPACE = "dxPointerEvents",
            MouseStrategyEventMap = {
                dxpointerdown: "mousedown",
                dxpointermove: "mousemove",
                dxpointerup: "mouseup",
                dxpointercancel: ""
            },
            TouchStrategyEventMap = {
                dxpointerdown: "touchstart",
                dxpointermove: "touchmove",
                dxpointerup: "touchend",
                dxpointercancel: "touchcancel"
            },
            PointerStrategyEventMap = {
                dxpointerdown: "pointerdown",
                dxpointermove: "pointermove",
                dxpointerup: "pointerup",
                dxpointercancel: "pointercancel"
            },
            MouseAndTouchStrategyEventMap = {
                dxpointerdown: "touchstart mousedown",
                dxpointermove: "touchmove mousemove",
                dxpointerup: "touchend mouseup",
                dxpointercancel: "touchcancel"
            };
        var eventMap = function() {
                if (support.touch && !(device.tablet || device.phone))
                    return MouseAndTouchStrategyEventMap;
                if (support.touch)
                    return TouchStrategyEventMap;
                return MouseStrategyEventMap
            }();
        $.each(eventMap, function(pointerEvent, originalEvents) {
            var SingleEventStrategy = {
                    EVENT_NAMESPACE: [POINTER_EVENTS_NAMESPACE, ".", pointerEvent].join(""),
                    _handlerCount: 0,
                    _handler: function(e) {
                        return events.fireEvent({
                                type: pointerEvent,
                                pointerType: events.eventSource(e),
                                originalEvent: e
                            })
                    },
                    setup: function() {
                        if (pointerEventNS._handlerCount > 0)
                            return;
                        $(document).on(events.addNamespace(originalEvents, SingleEventStrategy.EVENT_NAMESPACE), pointerEventNS._handler)
                    },
                    add: function() {
                        pointerEventNS._handlerCount++
                    },
                    remove: function() {
                        pointerEventNS._handlerCount--
                    },
                    teardown: function() {
                        if (pointerEventNS._handlerCount)
                            return;
                        $(document).off("." + pointerEventNS.EVENT_NAMESPACE)
                    }
                };
            var MultiEventStrategy = $.extend({}, SingleEventStrategy, {_handler: function(e) {
                        if (events.isTouchEvent(e))
                            pointerEventNS._skipNextEvents = true;
                        if (events.isMouseEvent(e) && mouseLocked)
                            return;
                        if (events.isMouseEvent(e) && pointerEventNS._skipNextEvents) {
                            pointerEventNS._skipNextEvents = false;
                            mouseLocked = true;
                            clearTimeout(unlockMouseTimer);
                            unlockMouseTimer = setTimeout(function() {
                                mouseLocked = false
                            }, MOUSE_EVENT_LOCK_TIMEOUT);
                            return
                        }
                        return SingleEventStrategy._handler(e)
                    }});
            var pointerEventNS = specialNS[pointerEvent] = eventMap === MouseAndTouchStrategyEventMap ? MultiEventStrategy : SingleEventStrategy
        });
        DX.ui.events.__internals = DX.ui.events.__internals || {};
        $.extend(DX.ui.events.__internals, {
            mouseLocked: function(value) {
                if (value === undefined)
                    return mouseLocked;
                mouseLocked = value
            },
            unlockMouseTimer: function() {
                return unlockMouseTimer
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.click.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            events = ui.events,
            jqSpecialEvent = $.event.special,
            EVENTS_NAME_SPACE = "dxSpecialEvents",
            CLICK_NAME_SPACE = "dxClick",
            CLICK_EVENT_NAME = "dxclick",
            CLICK_DATA_KEY = EVENTS_NAME_SPACE + "." + CLICK_NAME_SPACE,
            SCROLLABLE_PARENT_DATA_KEY = "dxClickScrollableParent",
            SCROLLABLE_PARENT_SCROLL_OFFSET_DATA_KEY = "dxClickScrollableParentOffset";
        var SimulatedStrategy = {
                TOUCH_BOUNDARY: 10,
                _startX: 0,
                _startY: 0,
                _handlerCount: 0,
                _touchWasMoved: function(e) {
                    var boundary = SimulatedStrategy.TOUCH_BOUNDARY;
                    return Math.abs(e.pageX - SimulatedStrategy._startX) > boundary || Math.abs(e.pageY - SimulatedStrategy._startY) > boundary
                },
                _getClosestScrollable: function($element) {
                    var $scrollParent = $();
                    if ($element.data(SCROLLABLE_PARENT_DATA_KEY))
                        $scrollParent = $element.data(SCROLLABLE_PARENT_DATA_KEY);
                    else {
                        var $current = $element;
                        while ($current.length) {
                            if ($current[0].scrollHeight > $current[0].offsetHeight) {
                                $scrollParent = $current;
                                $element.data(SCROLLABLE_PARENT_DATA_KEY, $scrollParent);
                                break
                            }
                            $current = $current.parent()
                        }
                    }
                    return $scrollParent
                },
                _saveClosestScrollableOffset: function($element) {
                    var $scrollable = SimulatedStrategy._getClosestScrollable($element);
                    if ($scrollable.length)
                        $element.data(SCROLLABLE_PARENT_SCROLL_OFFSET_DATA_KEY, $scrollable.scrollTop())
                },
                _closestScrollableWasMoved: function($element) {
                    var $scrollable = $element.data(SCROLLABLE_PARENT_DATA_KEY);
                    return $scrollable && $scrollable.scrollTop() !== $element.data(SCROLLABLE_PARENT_SCROLL_OFFSET_DATA_KEY)
                },
                _handleStart: function(e) {
                    if (events.isMouseEvent(e) && e.which !== 1)
                        return;
                    $(e.currentTarget).data(CLICK_DATA_KEY).trackingClick = true;
                    SimulatedStrategy._saveClosestScrollableOffset($(e.target));
                    SimulatedStrategy._startX = e.pageX;
                    SimulatedStrategy._startY = e.pageY
                },
                _handleEnd: function(e) {
                    var data = $(e.currentTarget).data(CLICK_DATA_KEY);
                    if (SimulatedStrategy._touchWasMoved(e)) {
                        data.trackingClick = false;
                        return
                    }
                    if (!data.trackingClick)
                        return;
                    data.trackingClick = false;
                    if (SimulatedStrategy._closestScrollableWasMoved($(e.target)))
                        return;
                    events.fireEvent({
                        type: CLICK_EVENT_NAME,
                        originalEvent: e
                    })
                },
                _handleCancel: function(e) {
                    $(e.currentTarget).data(CLICK_DATA_KEY).trackingClick = false
                },
                setup: function() {
                    if (SimulatedStrategy._handlerCount > 0)
                        return;
                    $(document).data(CLICK_DATA_KEY, {}).on(events.addNamespace("dxpointerdown", CLICK_NAME_SPACE), $.proxy(SimulatedStrategy._handleStart, this)).on(events.addNamespace("dxpointerup", CLICK_NAME_SPACE), $.proxy(SimulatedStrategy._handleEnd, this)).on(events.addNamespace("dxpointercancel", CLICK_NAME_SPACE), $.proxy(SimulatedStrategy._handleCancel, this))
                },
                add: function() {
                    SimulatedStrategy._handlerCount++
                },
                remove: function() {
                    SimulatedStrategy._handlerCount--
                },
                teardown: function() {
                    if (SimulatedStrategy._handlerCount)
                        return;
                    $(document).off("." + CLICK_NAME_SPACE).removeData(CLICK_DATA_KEY)
                }
            };
        var NativeStrategy = {
                bindType: "click",
                delegateType: "click"
            };
        jqSpecialEvent[CLICK_EVENT_NAME] = NativeStrategy;
        DX.ui.events.__internals = DX.ui.events.__internals || {};
        $.extend(DX.ui.events.__internals, {
            NativeClickStrategy: NativeStrategy,
            SimulatedClickStrategy: SimulatedStrategy
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.hold.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            events = ui.events,
            jqSpecialEvent = $.event.special,
            EVENTS_NAME_SPACE = "dxSpecialEvents",
            HOLD_NAME_SPACE = "dxHold",
            HOLD_EVENT_NAME = "dxhold",
            HOLD_TIMER_DATA_KEY = EVENTS_NAME_SPACE + "HoldTimer";
        var hold = jqSpecialEvent[HOLD_EVENT_NAME] = {
                HOLD_TIMEOUT: 750,
                TOUCH_BOUNDARY: 10,
                _startX: 0,
                _startY: 0,
                _touchWasMoved: function(e) {
                    var boundary = hold.TOUCH_BOUNDARY;
                    return Math.abs(e.pageX - hold._startX) > boundary || Math.abs(e.pageY - hold._startY) > boundary
                },
                setup: function(data) {
                    var element = this,
                        $element = $(element);
                    var handleStart = function(e) {
                            if ($element.data(HOLD_TIMER_DATA_KEY))
                                return;
                            hold._startX = e.pageX;
                            hold._startY = e.pageY;
                            $element.data(HOLD_TIMER_DATA_KEY, setTimeout(function() {
                                $element.removeData(HOLD_TIMER_DATA_KEY);
                                events.fireEvent({
                                    type: HOLD_EVENT_NAME,
                                    originalEvent: e
                                })
                            }, data && "timeout" in data ? data.timeout : hold.HOLD_TIMEOUT))
                        };
                    var handleMove = function(e) {
                            if (!hold._touchWasMoved(e))
                                return;
                            handleEnd()
                        };
                    var handleEnd = function() {
                            clearTimeout($element.data(HOLD_TIMER_DATA_KEY));
                            $element.removeData(HOLD_TIMER_DATA_KEY)
                        };
                    $element.on(events.addNamespace("dxpointerdown", HOLD_NAME_SPACE), handleStart).on(events.addNamespace("dxpointermove", HOLD_NAME_SPACE), handleMove).on(events.addNamespace("dxpointerup", HOLD_NAME_SPACE), handleEnd)
                },
                teardown: function() {
                    var $element = $(this);
                    clearTimeout($element.data(HOLD_TIMER_DATA_KEY));
                    $element.removeData(HOLD_TIMER_DATA_KEY).off("." + HOLD_NAME_SPACE)
                }
            }
    })(jQuery, DevExpress);
    /*! Module core, file ui.events.swipe.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            utils = DX.utils,
            events = ui.events,
            jqSpecialEvent = $.event.special,
            SWIPE_START_EVENT_NAME = "dxswipestart",
            SWIPE_EVENT_NAME = "dxswipe",
            SWIPE_END_EVENT_NAME = "dxswipeend",
            SWIPE_CANCEL_EVENT_NAME = "dxswipecancel",
            SWIPEABLE_DATA_KEY = "dxSwipeEventDataKey",
            GESTURE_LOCK_KEY = "dxGesture";
        var HorizontalStrategy = {
                defaultItemSizeFunc: function() {
                    return this._activeSwipeable.width()
                },
                isSwipeAngleAllowed: function(delta) {
                    return Math.abs(delta.y) <= Math.abs(delta.x)
                },
                getBounds: function() {
                    return [this._maxLeftOffset, this._maxRightOffset]
                },
                calcOffsetRatio: function(e) {
                    var endEventData = events.eventData(e);
                    return (endEventData.x - (this._startEventData && this._startEventData.x || 0)) / this._itemSizeFunc().call(this, e)
                },
                isFastSwipe: function(e) {
                    var endEventData = events.eventData(e);
                    return this.FAST_SWIPE_SPEED_LIMIT * Math.abs(endEventData.x - this._tickData.x) >= endEventData.time - this._tickData.time
                }
            };
        var VerticalStrategy = {
                defaultItemSizeFunc: function() {
                    return this._activeSwipeable.height()
                },
                isSwipeAngleAllowed: function(delta) {
                    return Math.abs(delta.y) >= Math.abs(delta.x)
                },
                getBounds: function() {
                    return [this._maxTopOffset, this._maxBottomOffset]
                },
                calcOffsetRatio: function(e) {
                    var endEventData = events.eventData(e);
                    return (endEventData.y - (this._startEventData && this._startEventData.y || 0)) / this._itemSizeFunc().call(this, e)
                },
                isFastSwipe: function(e) {
                    var endEventData = events.eventData(e);
                    return this.FAST_SWIPE_SPEED_LIMIT * Math.abs(endEventData.y - this._tickData.y) >= endEventData.time - this._tickData.time
                }
            };
        var STRATEGIES = {
                horizontal: HorizontalStrategy,
                vertical: VerticalStrategy
            };
        var SwipeDispatcher = DX.Class.inherit({
                STAGE_SLEEP: 0,
                STAGE_TOUCHED: 1,
                STAGE_SWIPING: 2,
                TICK_INTERVAL: 300,
                FAST_SWIPE_SPEED_LIMIT: 5,
                ctor: function() {
                    this._attachEvents()
                },
                _getStrategy: function() {
                    return STRATEGIES[this._data("direction")]
                },
                _defaultItemSizeFunc: function() {
                    return this._getStrategy().defaultItemSizeFunc.call(this)
                },
                _itemSizeFunc: function() {
                    return this._data("itemSizeFunc") || this._defaultItemSizeFunc
                },
                _data: function(key, value) {
                    var data = this._activeSwipeable.data(SWIPEABLE_DATA_KEY);
                    if (arguments.length === 1)
                        return data[key];
                    else if (arguments.length === 2)
                        data[key] = value
                },
                _closestSwipeable: function(e) {
                    var current = $(e.target);
                    while (current.length) {
                        var swipeable = $(current).data(SWIPEABLE_DATA_KEY);
                        if (swipeable)
                            return $(current);
                        current = current.parent()
                    }
                },
                _handleStart: function(e) {
                    if (events.needSkipEvent(e))
                        return;
                    if (this._swipeStage > this.STAGE_SLEEP)
                        return;
                    var activeSwipeable = this._activeSwipeable = this._closestSwipeable(e);
                    if (!activeSwipeable)
                        return;
                    this._parentsLength = this._activeSwipeable.parents().length;
                    this._startEventData = events.eventData(e);
                    this._tickData = {time: 0};
                    this._swipeStage = this.STAGE_TOUCHED;
                    if (events.isMouseEvent(e)) {
                        if ($(":focus", activeSwipeable).length)
                            utils.resetActiveElement();
                        e.preventDefault()
                    }
                },
                _handleMove: function(e) {
                    if (!this._activeSwipeable || this._swipeStage === this.STAGE_SLEEP)
                        return;
                    if (this._swipeStage === this.STAGE_TOUCHED)
                        this._handleFirstMove(e);
                    if (this._swipeStage === this.STAGE_SWIPING)
                        this._handleNextMoves(e)
                },
                _handleFirstMove: function(e) {
                    var delta = events.eventDelta(this._startEventData, events.eventData(e));
                    if (!delta.x && !delta.y)
                        return;
                    if (!this._getStrategy().isSwipeAngleAllowed.call(this, delta) || events.needSkipEvent(e)) {
                        this._reset();
                        return
                    }
                    var direction = this._data("direction");
                    if (e.originalEvent.pointerMoveData[direction] !== this._parentsLength)
                        return;
                    e.originalEvent.isScrollingEvent = false;
                    this._activeSwipeable.data(GESTURE_LOCK_KEY, true);
                    e = events.fireEvent({
                        type: "dxswipestart",
                        originalEvent: e,
                        target: this._activeSwipeable.get(0)
                    });
                    if (e.cancel) {
                        events.fireEvent({
                            type: "dxswipecancel",
                            originalEvent: e,
                            target: this._activeSwipeable.get(0)
                        });
                        this._reset();
                        return
                    }
                    this._maxLeftOffset = e.maxLeftOffset;
                    this._maxRightOffset = e.maxRightOffset;
                    this._maxTopOffset = e.maxTopOffset;
                    this._maxBottomOffset = e.maxBottomOffset;
                    this._swipeStage = this.STAGE_SWIPING
                },
                _handleBodyPointerMove: function(e) {
                    if (!this._activeSwipeable || !e.originalEvent)
                        return;
                    var pointerMoveData = e.originalEvent.pointerMoveData || {},
                        direction = this._data("direction"),
                        directionValue = pointerMoveData[direction];
                    if (directionValue && directionValue > this._parentsLength) {
                        this._reset();
                        return
                    }
                    pointerMoveData[direction] = this._parentsLength;
                    e.originalEvent.pointerMoveData = pointerMoveData
                },
                _handleNextMoves: function(e) {
                    var strategy = this._getStrategy(),
                        moveEventData = events.eventData(e),
                        offset = strategy.calcOffsetRatio.call(this, e);
                    offset = this._fitOffset(offset, this._data("elastic"));
                    if (moveEventData.time - this._tickData.time > this.TICK_INTERVAL)
                        this._tickData = moveEventData;
                    events.fireEvent({
                        type: "dxswipe",
                        originalEvent: e,
                        offset: offset,
                        target: this._activeSwipeable.get(0)
                    })
                },
                _handleEnd: function(e) {
                    if (!DX.devices.isRippleEmulator() && events.hasTouches(e) || !this._activeSwipeable)
                        return;
                    if (this._swipeStage !== this.STAGE_SWIPING) {
                        this._reset();
                        return
                    }
                    var strategy = this._getStrategy(),
                        offsetRatio = strategy.calcOffsetRatio.call(this, e),
                        fast = strategy.isFastSwipe.call(this, e),
                        startOffset = offsetRatio,
                        targetOffset = this._calcTargetOffset(offsetRatio, fast);
                    startOffset = this._fitOffset(startOffset, this._data("elastic"));
                    targetOffset = this._fitOffset(targetOffset, false);
                    events.fireEvent({
                        type: "dxswipeend",
                        offset: startOffset,
                        targetOffset: targetOffset,
                        target: this._activeSwipeable.get(0),
                        originalEvent: e
                    });
                    this._reset()
                },
                _fitOffset: function(offset, elastic) {
                    var strategy = this._getStrategy(),
                        bounds = strategy.getBounds.call(this);
                    if (offset < -bounds[0])
                        return elastic ? (-2 * bounds[0] + offset) / 3 : -bounds[0];
                    if (offset > bounds[1])
                        return elastic ? (2 * bounds[1] + offset) / 3 : bounds[1];
                    return offset
                },
                _calcTargetOffset: function(offsetRatio, fast) {
                    var result;
                    if (fast) {
                        result = Math.ceil(Math.abs(offsetRatio));
                        if (offsetRatio < 0)
                            result = -result
                    }
                    else
                        result = Math.round(offsetRatio);
                    return result
                },
                _reset: function() {
                    this._activeSwipeable.data(GESTURE_LOCK_KEY, false);
                    this._activeSwipeable = null;
                    this._swipeStage = this.STAGE_SLEEP
                },
                _attachEvents: function() {
                    $("body").on(events.addNamespace("dxpointermove", "dxSwipe"), $.proxy(this._handleBodyPointerMove, this));
                    $(document).on(events.addNamespace("dxpointerdown", "dxSwipe"), $.proxy(this._handleStart, this)).on(events.addNamespace("dxpointermove", "dxSwipe"), $.proxy(this._handleMove, this)).on(events.addNamespace("dxpointerup", "dxSwipe"), $.proxy(this._handleEnd, this))
                },
                isDisposed: function() {
                    return this._disposed
                },
                dispose: function() {
                    this._disposed = true;
                    if (this._activeSwipeable)
                        this._reset();
                    $(document).off(".dxSwipe")
                }
            });
        var swipeDispatcher = null;
        $.each([SWIPE_START_EVENT_NAME, SWIPE_EVENT_NAME, SWIPE_END_EVENT_NAME, SWIPE_CANCEL_EVENT_NAME], function() {
            jqSpecialEvent[this] = {
                noBubble: true,
                setup: function(data) {
                    $(this).data(SWIPEABLE_DATA_KEY, $.extend($(this).data(SWIPEABLE_DATA_KEY) || {
                        elastic: true,
                        direction: "horizontal"
                    }, data));
                    if (!swipeDispatcher || swipeDispatcher.isDisposed())
                        swipeDispatcher = new SwipeDispatcher
                },
                add: function() {
                    var data = $(this).data(SWIPEABLE_DATA_KEY);
                    data.handlerCount = data.handlerCount || 0;
                    data.handlerCount++
                },
                remove: function() {
                    var data = $(this).data(SWIPEABLE_DATA_KEY);
                    data.handlerCount = data.handlerCount || 0;
                    data.handlerCount--
                },
                teardown: function() {
                    var element = $(this),
                        data = $(this).data(SWIPEABLE_DATA_KEY);
                    if (data && data.handlerCount)
                        return;
                    element.removeData(SWIPEABLE_DATA_KEY);
                    if (!swipeDispatcher)
                        return;
                    swipeDispatcher.dispose();
                    swipeDispatcher = null
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.component.js */
    (function($, DX, undefined) {
        var COMPONENT_NAMES_DATA_KEY = "dxComponents",
            ui = DX.ui,
            dataUtils = DX.data.utils;
        var Component = DX.Class.inherit({
                NAME: null,
                _defaultOptions: function() {
                    return {disabled: false}
                },
                ctor: function(element, options) {
                    if (!this.NAME)
                        throw Error("NAME is not specified");
                    this._$element = $(element);
                    this._element().data(this.NAME, this);
                    if (!this._element().data(COMPONENT_NAMES_DATA_KEY))
                        this._element().data(COMPONENT_NAMES_DATA_KEY, []);
                    this._element().data(COMPONENT_NAMES_DATA_KEY).push(this.NAME);
                    this._options = {};
                    this._updateLockCount = 0;
                    this._requireRefresh = false;
                    this.optionChanged = $.Callbacks();
                    this.disposing = $.Callbacks();
                    this.beginUpdate();
                    try {
                        var device = DX.devices.current(),
                            optionsByDevice = ui.optionsByDevice(device, this.NAME) || {};
                        this.option(this._defaultOptions());
                        this.option(optionsByDevice);
                        this._initOptions(options || {})
                    }
                    finally {
                        this.endUpdate()
                    }
                },
                _initOptions: function(options) {
                    this.option(options)
                },
                _optionValuesEqual: function(name, oldValue, newValue) {
                    oldValue = dataUtils.toComparable(oldValue, true);
                    newValue = dataUtils.toComparable(newValue, true);
                    if (oldValue === null || typeof oldValue !== "object")
                        return oldValue === newValue;
                    return false
                },
                _init: $.noop,
                _render: $.noop,
                _clean: $.noop,
                _modelByElement: $.noop,
                _invalidate: function() {
                    if (!this._updateLockCount)
                        throw Error("Invalidate called outside update transaction");
                    this._requireRefresh = true
                },
                _refresh: function() {
                    this._clean();
                    this._render()
                },
                _dispose: function() {
                    this._clean();
                    this.optionChanged.empty();
                    this.disposing.fireWith(this).empty()
                },
                _createAction: function(actionSource, config) {
                    var self = this;
                    config = $.extend({}, config);
                    var element = config.element || self._element(),
                        model = self._modelByElement(element);
                    config.context = model || self;
                    config.component = self;
                    var action = new DX.Action(actionSource, config);
                    return function(e) {
                            if (!arguments.length)
                                e = {};
                            if (e instanceof $.Event)
                                throw Error("Action must be executed with jQuery.Event like action({ jQueryEvent: event })");
                            if (!$.isPlainObject(e))
                                e = {actionValue: e};
                            return action.execute.call(action, $.extend(e, {
                                    component: self,
                                    element: element,
                                    model: model
                                }))
                        }
                },
                _createActionByOption: function(optionName, config) {
                    if (typeof optionName !== "string")
                        throw Error("Option name type is unexpected");
                    return this._createAction(this.option(optionName), config)
                },
                _optionChanged: function(name, value, prevValue){},
                _element: function() {
                    return this._$element
                },
                instance: function() {
                    return this
                },
                beginUpdate: function() {
                    this._updateLockCount++
                },
                endUpdate: function() {
                    this._updateLockCount--;
                    if (!this._updateLockCount)
                        if (!this._initializing && !this._initialized) {
                            this._initializing = true;
                            try {
                                this._init()
                            }
                            finally {
                                this._initializing = false;
                                this._initialized = true
                            }
                            this._render()
                        }
                        else if (this._requireRefresh) {
                            this._requireRefresh = false;
                            this._refresh()
                        }
                },
                option: function(options) {
                    var self = this,
                        name = options,
                        value = arguments[1];
                    if (arguments.length < 2 && $.type(name) !== "object")
                        return dataUtils.compileGetter(name)(self._options, {functionsAsIs: true});
                    if (typeof name === "string") {
                        options = {};
                        options[name] = value
                    }
                    self.beginUpdate();
                    try {
                        $.each(options, function(name, value) {
                            var prevValue = dataUtils.compileGetter(name)(self._options, {functionsAsIs: true}),
                                topLevelName;
                            if (self._optionValuesEqual(name, prevValue, value))
                                return;
                            dataUtils.compileSetter(name)(self._options, value, {
                                functionsAsIs: true,
                                merge: true
                            });
                            topLevelName = name.split(/[.\[]/)[0];
                            if (self._initialized) {
                                self.optionChanged.fireWith(self, [topLevelName, value, prevValue]);
                                self._optionChanged(topLevelName, value, prevValue)
                            }
                        })
                    }
                    finally {
                        self.endUpdate()
                    }
                }
            });
        var registerComponent = function(name, componentClass) {
                ui[name] = componentClass;
                componentClass.prototype.NAME = name;
                $.fn[name] = function(options) {
                    var isMemberInvoke = typeof options === "string",
                        result = this;
                    if (isMemberInvoke) {
                        var memberName = options,
                            memberArgs = $.makeArray(arguments).slice(1);
                        this.each(function() {
                            var instance = $(this).data(name);
                            if (!instance)
                                throw Error(DX.utils.stringFormat("Component {0} has not been initialized on this element", name));
                            var member = instance[memberName],
                                memberValue = member.apply(instance, memberArgs);
                            if (memberValue !== undefined) {
                                result = memberValue;
                                return false
                            }
                        })
                    }
                    else
                        this.each(function() {
                            var instance = $(this).data(name);
                            if (instance)
                                instance.option(options);
                            else
                                new componentClass(this, options)
                        });
                    return result
                }
            };
        var getComponents = function(element) {
                element = $(element);
                var names = element.data(COMPONENT_NAMES_DATA_KEY);
                if (!names)
                    return [];
                return $.map(names, function(name) {
                        return element.data(name)
                    })
            };
        var disposeComponents = function() {
                $.each(getComponents(this), function() {
                    this._dispose()
                })
            };
        var originalCleanData = $.cleanData;
        $.cleanData = function(element) {
            $.each(element, disposeComponents);
            return originalCleanData.apply(this, arguments)
        };
        $.extend(ui, {
            Component: Component,
            registerComponent: registerComponent
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.knockoutIntegration.js */
    (function($, DX, undefined) {
        var ko = window.ko;
        if (!DX.support.hasKo)
            return;
        (function checkKnockoutVersion(version) {
            version = version.split(".");
            if (version[0] < 2 || version[0] == 2 && version[1] < 3)
                throw Error("Your version of KnockoutJS is too old. Please upgrade KnockoutJS to 2.3.0 or later.");
        })(ko.version);
        var ui = DX.ui,
            LOCKS_DATA_KEY = "dxKoLocks",
            CREATED_WITH_KO_DATA_KEY = "dxKoCreation";
        var Locks = function() {
                var info = {};
                var currentCount = function(lockName) {
                        return info[lockName] || 0
                    };
                return {
                        obtain: function(lockName) {
                            info[lockName] = currentCount(lockName) + 1
                        },
                        release: function(lockName) {
                            var count = currentCount(lockName);
                            if (count < 1)
                                throw Error("Not locked");
                            if (count === 1)
                                delete info[lockName];
                            else
                                info[lockName] = count - 1
                        },
                        locked: function(lockName) {
                            return currentCount(lockName) > 0
                        }
                    }
            };
        var registerComponentKoBinding = function(componentName) {
                ko.bindingHandlers[componentName] = {init: function(domNode, valueAccessor) {
                        var element = $(domNode),
                            ctorOptions = {},
                            optionNameToModelMap = {};
                        var applyModelValueToOption = function(optionName, modelValue) {
                                var component = element.data(componentName),
                                    locks = element.data(LOCKS_DATA_KEY),
                                    optionValue = ko.utils.unwrapObservable(modelValue);
                                if (!component) {
                                    ctorOptions[optionName] = optionValue;
                                    if (ko.isWriteableObservable(modelValue))
                                        optionNameToModelMap[optionName] = modelValue
                                }
                                else {
                                    if (locks.locked(optionName))
                                        return;
                                    locks.obtain(optionName);
                                    try {
                                        component.option(optionName, optionValue)
                                    }
                                    finally {
                                        locks.release(optionName)
                                    }
                                }
                            };
                        var handleOptionChanged = function(optionName, optionValue) {
                                if (!(optionName in optionNameToModelMap))
                                    return;
                                var element = this._$element,
                                    locks = element.data(LOCKS_DATA_KEY);
                                if (locks.locked(optionName))
                                    return;
                                locks.obtain(optionName);
                                try {
                                    optionNameToModelMap[optionName](optionValue)
                                }
                                finally {
                                    locks.release(optionName)
                                }
                            };
                        ko.computed(function() {
                            var cmp = element.data(componentName);
                            if (cmp)
                                cmp.beginUpdate();
                            $.each(ko.unwrap(valueAccessor()), function(modelName, modelValueExpr) {
                                ko.computed(function() {
                                    applyModelValueToOption(modelName, modelValueExpr)
                                }, null, {disposeWhenNodeIsRemoved: domNode})
                            });
                            if (cmp)
                                cmp.endUpdate()
                        }, null, {disposeWhenNodeIsRemoved: domNode});
                        if (ctorOptions) {
                            element.data(CREATED_WITH_KO_DATA_KEY, true);
                            element[componentName](ctorOptions);
                            ctorOptions = null;
                            element.data(LOCKS_DATA_KEY, new Locks);
                            element.data(componentName).optionChanged.add(handleOptionChanged)
                        }
                        return {controlsDescendantBindings: ui[componentName].subclassOf(ui.Widget)}
                    }}
            };
        var KoComponent = ui.Component.inherit({_modelByElement: function(element) {
                    if (element.length)
                        return ko.dataFor(element.get(0))
                }});
        var originalRegisterComponent = ui.registerComponent;
        var registerKoComponent = function(name, componentClass) {
                originalRegisterComponent(name, componentClass);
                registerComponentKoBinding(name)
            };
        var KoTemplate = ui.Template.inherit({
                ctor: function(element) {
                    this.callBase.apply(this, arguments);
                    this._template = $("<div>").append(element);
                    this._registerKoTemplate()
                },
                _cleanTemplateElement: function() {
                    this._element.each(function() {
                        ko.cleanNode(this)
                    })
                },
                _registerKoTemplate: function() {
                    var template = this._template.get(0);
                    new ko.templateSources.anonymousTemplate(template)['nodes'](template)
                },
                render: function(container, data) {
                    data = data !== undefined ? data : ko.dataFor(container.get(0)) || {};
                    var containerBindingContext = ko.contextFor(container[0]);
                    var bindingContext = containerBindingContext ? containerBindingContext.createChildContext(data) : data;
                    var renderBag = $("<div />").appendTo(container);
                    ko.renderTemplate(this._template.get(0), bindingContext, null, renderBag.get(0));
                    var result = renderBag.contents();
                    container.append(result);
                    renderBag.remove();
                    return result
                },
                dispose: function() {
                    this._template.remove()
                }
            });
        var KoTemplateProvider = ui.TemplateProvider.inherit({
                getTemplateClass: function() {
                    return KoTemplate
                },
                supportDefaultTemplate: function(widget) {
                    return this._createdWithKo(widget) ? true : this.callBase(widget)
                },
                getDefaultTemplate: function(widget) {
                    if (this._createdWithKo(widget))
                        return defaultKoTemplate(widget.NAME)
                },
                _createdWithKo: function(widget) {
                    return !!widget._element().data(CREATED_WITH_KO_DATA_KEY)
                }
            });
        ko.bindingHandlers.dxAction = {update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
                var $element = $(element);
                var actionSource = ko.utils.unwrapObservable(valueAccessor()),
                    action = new DX.Action(actionSource, {context: element});
                $element.off(".dxActionBinding").on("dxclick.dxActionBinding", function() {
                    action.execute({
                        element: $element,
                        model: viewModel,
                        evaluate: function(expression) {
                            var context = viewModel;
                            if (expression.length > 0 && expression[0] === "$")
                                context = ko.contextFor(element);
                            var getter = DX.data.utils.compileGetter(expression);
                            return getter(context)
                        }
                    })
                })
            }};
        var defaultKoTemplate = function() {
                var cache = {};
                return function(widgetName) {
                        if (!DEFAULT_ITEM_TEMPLATE_GENERATORS[widgetName])
                            widgetName = "base";
                        if (!cache[widgetName]) {
                            var html = DEFAULT_ITEM_TEMPLATE_GENERATORS[widgetName](),
                                markup = DX.utils.createMarkupFromString(html);
                            cache[widgetName] = new KoTemplate(markup)
                        }
                        return cache[widgetName]
                    }
            }();
        var createElementWithBindAttr = function(tagName, bindings, closeTag, additionalProperties) {
                closeTag = closeTag === undefined ? true : closeTag;
                var bindAttr = $.map(bindings, function(value, key) {
                        return key + ":" + value
                    }).join(",");
                additionalProperties = additionalProperties || "";
                return "<" + tagName + " data-bind=\"" + bindAttr + "\" " + additionalProperties + ">" + (closeTag ? "</" + tagName + ">" : "")
            };
        var defaultKoTemplateBasicBindings = {css: "{ 'dx-state-disabled': $data.disabled, 'dx-state-invisible': !$data.visible && $data.visible !== undefined }"};
        var DEFAULT_ITEM_TEMPLATE_GENERATORS = {base: function() {
                    var template = [createElementWithBindAttr("div", defaultKoTemplateBasicBindings, false)],
                        htmlBinding = createElementWithBindAttr("div", {html: "html"}),
                        textBinding = createElementWithBindAttr("div", {text: "text"}),
                        primitiveBinding = createElementWithBindAttr("div", {text: "String($data)"});
                    template.push("<!-- ko if: $data.html && !$data.text -->", htmlBinding, "<!-- /ko -->", "<!-- ko if: !$data.html && $data.text -->", textBinding, "<!-- /ko -->", "<!-- ko ifnot: $.isPlainObject($data) -->", primitiveBinding, "<!-- /ko -->", "</div>");
                    return template.join("")
                }};
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxPivotTabs = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(),
                titleBinding = createElementWithBindAttr("span", {text: "title"});
            var divInnerStart = template.indexOf(">") + 1,
                divInnerFinish = template.length - 6;
            template = [template.substring(0, divInnerStart), titleBinding, template.substring(divInnerFinish, template.length)];
            return template.join("")
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxPanorama = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(),
                headerBinding = createElementWithBindAttr("div", {text: "header"}, true, 'class="dx-panorama-item-header"');
            var divInnerStart = template.indexOf(">") + 1;
            template = [template.substring(0, divInnerStart), "<!-- ko if: $data.header -->", headerBinding, "<!-- /ko -->", template.substring(divInnerStart, template.length)];
            return template.join("")
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxList = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(),
                keyBinding = createElementWithBindAttr("div", {text: "key"});
            template = [template.substring(0, template.length - 6), "<!-- ko if: $data.key -->" + keyBinding + "<!-- /ko -->", "</div>"];
            return template.join("")
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxToolbar = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base();
            template = [template.substring(0, template.length - 6), "<!-- ko if: $data.widget -->"];
            $.each(["button", "tabs", "dropDownMenu"], function() {
                var bindingName = DX.inflector.camelize(["dx", "-", this].join("")),
                    bindingObj = {};
                bindingObj[bindingName] = "$data.options";
                template.push("<!-- ko if: $data.widget === '", this, "' -->", createElementWithBindAttr("div", bindingObj), "<!-- /ko -->")
            });
            template.push("<!-- /ko -->");
            return template.join("")
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxGallery = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(),
                primitiveBinding = createElementWithBindAttr("div", {text: "String($data)"}),
                imgBinding = createElementWithBindAttr("img", {attr: "{ src: String($data) }"}, false);
            template = template.replace(primitiveBinding, imgBinding);
            return template
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base(),
                baseTextBinding = createElementWithBindAttr("div", {text: "text"}),
                iconBinding = createElementWithBindAttr("span", {
                    attr: "{ 'class': 'dx-icon-' + $data.icon }",
                    css: "{ 'dx-icon': true }"
                }),
                iconSrcBinding = createElementWithBindAttr("img", {
                    attr: "{ src: $data.iconSrc }",
                    css: "{ 'dx-icon': true }"
                }, false),
                textBinding = "<!-- ko if: $data.icon -->" + iconBinding + "<!-- /ko -->" + "<!-- ko if: !$data.icon && $data.iconSrc -->" + iconSrcBinding + "<!-- /ko -->" + "<span class=\"dx-tab-text\" data-bind=\"text: $data.text\"></span>";
            template = template.replace("<!-- ko if: !$data.html && $data.text -->", "<!-- ko if: !$data.html && ($data.text || $data.icon || $data.iconSrc) -->").replace(baseTextBinding, textBinding);
            return template
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxActionSheet = function() {
            return createElementWithBindAttr("div", {dxButton: "{ text: $data.text, clickAction: $data.clickAction, type: $data.type, disabled: !!$data.disabled }"})
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxNavBar = DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs;
        var cleanKoData = function(element, andSelf) {
                var cleanNode = function() {
                        ko.cleanNode(this)
                    };
                if (andSelf)
                    element.each(cleanNode);
                else
                    element.find("*").each(cleanNode)
            };
        var originalEmpty = $.fn.empty;
        $.fn.empty = function() {
            cleanKoData(this, false);
            return originalEmpty.apply(this, arguments)
        };
        var originalRemove = $.fn.remove;
        $.fn.remove = function(selector, keepData) {
            if (!keepData) {
                var subject = this;
                if (selector)
                    subject = subject.filter(selector);
                cleanKoData(subject, true)
            }
            return originalRemove.call(this, selector, keepData)
        };
        var originalHtml = $.fn.html;
        $.fn.html = function(value) {
            if (typeof value === "string")
                cleanKoData(this, false);
            return originalHtml.apply(this, arguments)
        };
        $.extend(ui, {
            Component: KoComponent,
            registerComponent: registerKoComponent,
            TemplateProvider: KoTemplateProvider,
            Template: KoTemplate,
            defaultTemplate: defaultKoTemplate
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.angularIntegration.js */
    (function($, DX, undefined) {
        if (!DX.support.hasNg)
            return;
        var angular = window.angular,
            ui = DevExpress.ui,
            compileSetter = DX.data.utils.compileSetter,
            compileGetter = DX.data.utils.compileGetter;
        var CREATED_WITH_NG_DATA_KEY = "dxNgCreation",
            TEMPLATES_DATA_KEY = "dxTemplates",
            COMPILER_DATA_KEY = "dxNgCompiler",
            DEFAULT_COMPILER_DATA_KEY = "dxDefaultCompilerGetter",
            ANONYMOUS_TEMPLATE_NAME = "template";
        var phoneJsModule = angular.module("dx", []);
        var ComponentBuilder = DX.Class.inherit({
                ctor: function(options) {
                    this._componentName = options.componentName;
                    this._compile = options.compile;
                    this._$element = options.$element;
                    this._componentDisposing = $.Callbacks();
                    this._$templates = this._extractTemplates()
                },
                init: function(options) {
                    this._scope = options.scope;
                    this._$element = options.$element;
                    this._ngOptions = options.ngOptions;
                    this._$element.data(CREATED_WITH_NG_DATA_KEY, true);
                    if (options.ngOptions.data)
                        this._initDataScope(options.ngOptions.data)
                },
                initDefaultCompilerGetter: function() {
                    var self = this;
                    self._$element.data(DEFAULT_COMPILER_DATA_KEY, function($template) {
                        return self._compilerByTemplate($template)
                    })
                },
                initTemplateCompilers: function() {
                    var self = this;
                    if (this._$templates)
                        this._$templates.each(function(i, template) {
                            $(template).data(COMPILER_DATA_KEY, self._compilerByTemplate(template))
                        })
                },
                initComponentWithBindings: function() {
                    this._initComponent(this._scope);
                    this._initComponentBindings()
                },
                _initDataScope: function(data) {
                    if (typeof data === "string") {
                        var dataStr = data,
                            rootScope = this._scope;
                        data = rootScope.$eval(data);
                        this._scope = rootScope.$new();
                        this._synchronizeDataScopes(rootScope, this._scope, data, dataStr)
                    }
                    $.extend(this._scope, data)
                },
                _synchronizeDataScopes: function(parentScope, childScope, data, parentPrefix) {
                    var self = this;
                    $.each(data, function(fieldPath) {
                        self._synchronizeScopeField({
                            parentScope: parentScope,
                            childScope: childScope,
                            fieldPath: fieldPath,
                            parentPrefix: parentPrefix
                        })
                    })
                },
                _initComponent: function(scope) {
                    this._component = this._$element[this._componentName](this._evalOptions(scope)).data(this._componentName)
                },
                _initComponentBindings: function() {
                    var self = this,
                        optionDependencies = {};
                    if (self._ngOptions.bindingOptions)
                        $.each(self._ngOptions.bindingOptions, function(optionPath, valuePath) {
                            var separatorIndex = optionPath.search(/\[|\./),
                                optionForSubscribe = separatorIndex > -1 ? optionPath.substring(0, separatorIndex) : optionPath;
                            if (!optionDependencies[optionForSubscribe])
                                optionDependencies[optionForSubscribe] = {};
                            optionDependencies[optionForSubscribe][optionPath] = valuePath;
                            var clearWatcher = self._scope.$watch(valuePath, function(newValue, oldValue) {
                                    if (newValue !== oldValue)
                                        self._component.option(optionPath, newValue)
                                }, true);
                            self._component.disposing.add(function() {
                                clearWatcher();
                                self._componentDisposing.fire()
                            })
                        });
                    self._component.optionChanged.add(function(optionName, optionValue) {
                        if (self._scope.$root.$$phase || !optionDependencies || !optionDependencies[optionName])
                            return;
                        self._scope.$apply(function() {
                            $.each(optionDependencies[optionName], function(optionPath, valuePath) {
                                var setter = compileSetter(valuePath),
                                    getter = compileGetter(optionPath);
                                var tmpData = {};
                                tmpData[optionName] = optionValue;
                                setter(self._scope, getter(tmpData))
                            })
                        })
                    })
                },
                _extractTemplates: function() {
                    var $templates;
                    if (ui[this._componentName].subclassOf(ui.Widget) && $.trim(this._$element.html())) {
                        var isAnonymousTemplate = !this._$element.children().first().attr("data-options");
                        if (isAnonymousTemplate)
                            $templates = $("<div/>").attr("data-options", "dxTemplate: { name: '" + ANONYMOUS_TEMPLATE_NAME + "' }").append(this._$element.contents());
                        else
                            $templates = this._$element.children().detach();
                        this._$element.data(TEMPLATES_DATA_KEY, $templates)
                    }
                    return $templates
                },
                _compilerByTemplate: function(template) {
                    var self = this,
                        scopeItemsPath = this._getScopeItemsPath();
                    return function(data, index) {
                            var $resultMarkup = $(template).clone(),
                                templateScope;
                            if (data !== undefined) {
                                var dataIsScope = data.$id,
                                    templateScope = dataIsScope ? data : self._createScopeWithData(data);
                                $resultMarkup.on("$destroy", function() {
                                    var destroyAlreadyCalled = !templateScope.$parent;
                                    if (destroyAlreadyCalled)
                                        return;
                                    templateScope.$destroy()
                                })
                            }
                            else
                                templateScope = self._scope;
                            if (scopeItemsPath)
                                self._synchronizeScopes(templateScope, scopeItemsPath, index);
                            safeApply(self._compile($resultMarkup), templateScope);
                            return $resultMarkup
                        }
                },
                _getScopeItemsPath: function() {
                    if (ui[this._componentName].subclassOf(ui.CollectionContainerWidget) && this._ngOptions.bindingOptions)
                        return this._ngOptions.bindingOptions.items
                },
                _createScopeWithData: function(data) {
                    var newScope = this._scope.$new();
                    if (typeof data === "object")
                        $.extend(newScope, data);
                    else
                        newScope.scopeValue = data;
                    return newScope
                },
                _synchronizeScopes: function(itemScope, parentPrefix, itemIndex) {
                    var self = this,
                        item = compileGetter(parentPrefix + "[" + itemIndex + "]")(this._scope);
                    if (!$.isPlainObject(item))
                        item = {scopeValue: item};
                    $.each(item, function(itemPath) {
                        self._synchronizeScopeField({
                            parentScope: self._scope,
                            childScope: itemScope,
                            fieldPath: itemPath,
                            parentPrefix: parentPrefix,
                            itemIndex: itemIndex
                        })
                    })
                },
                _synchronizeScopeField: function(args) {
                    var parentScope = args.parentScope,
                        childScope = args.childScope,
                        fieldPath = args.fieldPath,
                        parentPrefix = args.parentPrefix,
                        itemIndex = args.itemIndex;
                    var innerPathSuffix = fieldPath === "scopeValue" ? "" : "." + fieldPath,
                        collectionField = itemIndex !== undefined,
                        optionOuterBag = [parentPrefix],
                        optionOuterPath;
                    if (collectionField)
                        optionOuterBag.push("[", itemIndex, "]");
                    optionOuterBag.push(innerPathSuffix);
                    optionOuterPath = optionOuterBag.join("");
                    var clearParentWatcher = parentScope.$watch(optionOuterPath, function(newValue, oldValue) {
                            if (newValue !== oldValue)
                                compileSetter(fieldPath)(childScope, newValue)
                        });
                    var clearItemWatcher = childScope.$watch(fieldPath, function(newValue, oldValue) {
                            if (newValue !== oldValue) {
                                if (collectionField && !compileGetter(parentPrefix)(parentScope)[itemIndex]) {
                                    clearItemWatcher();
                                    return
                                }
                                compileSetter(optionOuterPath)(parentScope, newValue)
                            }
                        });
                    this._componentDisposing.add([clearParentWatcher, clearItemWatcher])
                },
                _evalOptions: function(scope) {
                    var result = $.extend({}, this._ngOptions);
                    delete result.data;
                    delete result.bindingOptions;
                    if (this._ngOptions.bindingOptions)
                        $.each(this._ngOptions.bindingOptions, function(key, value) {
                            result[key] = scope.$eval(value)
                        });
                    return result
                }
            });
        var safeApply = function(func, scope) {
                if (scope.$root.$$phase)
                    func(scope);
                else
                    scope.$apply(function() {
                        func(scope)
                    })
            };
        var NgComponent = ui.Component.inherit({
                _modelByElement: function(element) {
                    if (element.length)
                        return element.scope()
                },
                _createActionByOption: function() {
                    var action = this.callBase.apply(this, arguments);
                    var component = this,
                        wrappedAction = function() {
                            var self = this,
                                scope = component._modelByElement(component._element()),
                                args = arguments;
                            if (!scope || scope.$root.$$phase)
                                return action.apply(self, args);
                            return scope.$apply(function() {
                                    return action.apply(self, args)
                                })
                        };
                    return wrappedAction
                }
            });
        var originalRegisterComponent = ui.registerComponent;
        var registerNgComponent = function(componentName, componentClass) {
                originalRegisterComponent(componentName, componentClass);
                phoneJsModule.directive(componentName, ["$compile", function(compile) {
                        return {
                                restrict: "A",
                                compile: function($element) {
                                    var componentBuilder = new ComponentBuilder({
                                            componentName: componentName,
                                            compile: compile,
                                            $element: $element
                                        });
                                    return function(scope, $element, attrs) {
                                            componentBuilder.init({
                                                scope: scope,
                                                $element: $element,
                                                ngOptions: attrs[componentName] ? scope.$eval(attrs[componentName]) : {}
                                            });
                                            componentBuilder.initTemplateCompilers();
                                            componentBuilder.initDefaultCompilerGetter();
                                            componentBuilder.initComponentWithBindings()
                                        }
                                }
                            }
                    }])
            };
        var NgTemplate = ui.Template.inherit({
                ctor: function() {
                    this.callBase.apply(this, arguments);
                    this._compiler = this._template.data(COMPILER_DATA_KEY)
                },
                render: function(container, data, index) {
                    var compiler = this._compiler,
                        result = $.isFunction(compiler) ? compiler(data, index) : compiler;
                    container.append(result);
                    return result
                },
                setCompiler: function(compilerGetter) {
                    this._compiler = compilerGetter(this._element)
                }
            });
        var NgTemplateProvider = ui.TemplateProvider.inherit({
                getTemplateClass: function(widget) {
                    if (this._createdWithNg(widget))
                        return NgTemplate;
                    return this.callBase(widget)
                },
                supportDefaultTemplate: function(widget) {
                    return this._createdWithNg(widget) ? true : this.callBase(widget)
                },
                getDefaultTemplate: function(widget) {
                    if (this._createdWithNg(widget)) {
                        var compilerGetter = widget._element().data(DEFAULT_COMPILER_DATA_KEY),
                            template = defaultNgTemplate(widget.NAME);
                        template.setCompiler(compilerGetter);
                        return template
                    }
                },
                _createdWithNg: function(widget) {
                    return !!widget._element().data(CREATED_WITH_NG_DATA_KEY)
                }
            });
        var defaultNgTemplate = function() {
                var cache = {};
                return function(widgetName) {
                        if (!DEFAULT_ITEM_TEMPLATE_GENERATORS[widgetName])
                            widgetName = "base";
                        if (!cache[widgetName])
                            cache[widgetName] = DEFAULT_ITEM_TEMPLATE_GENERATORS[widgetName]();
                        return new NgTemplate(cache[widgetName])
                    }
            }();
        var baseElements = {
                container: function() {
                    return $("<div/>").attr("ng-class", "{ 'dx-state-invisible': !visible && visible != undefined, 'dx-state-disabled': !!disabled }").attr("ng-switch", "").attr("on", "html && 'html' || text && 'text' || scopeValue && 'scopeValue'")
                },
                html: function() {
                    return $("<div/>").attr("ng-switch-when", "html").attr("ng-bind-html-unsafe", "html")
                },
                text: function() {
                    return $("<div/>").attr("ng-switch-when", "text").attr("ng-bind", "text")
                },
                primitive: function() {
                    return $("<div/>").attr("ng-switch-when", "scopeValue").attr("ng-bind-html-unsafe", "'' + scopeValue")
                }
            };
        var DEFAULT_ITEM_TEMPLATE_GENERATORS = {base: function() {
                    return baseElements.container().append(baseElements.html()).append(baseElements.text()).append(baseElements.primitive())
                }};
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxList = function() {
            return DEFAULT_ITEM_TEMPLATE_GENERATORS.base().attr("on", "html && 'html' || text && 'text' || scopeValue && 'scopeValue' || key && 'key'").append($("<div/>").attr("ng-switch-when", "key").attr("ng-bind", "key"))
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxToolbar = function() {
            var template = DEFAULT_ITEM_TEMPLATE_GENERATORS.base().attr("on", "html && 'html' || text && 'text' || scopeValue && 'scopeValue' || widget");
            $.each(["button", "tabs", "dropDownMenu"], function(i, widgetName) {
                var bindingName = "dx-" + DX.inflector.dasherize(this);
                $("<div/>").attr("ng-switch-when", widgetName).attr(bindingName, "options").appendTo(template)
            });
            return template
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxGallery = function() {
            return baseElements.container().append(baseElements.html()).append(baseElements.text()).append($("<img/>").attr("ng-switch-when", "scopeValue").attr("ng-src", "{{'' + scopeValue}}"))
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs = function() {
            var container = baseElements.container().attr("on", "html && 'html' ||  icon && 'icon' ||  iconSrc && 'iconSrc' ||  text && 'text' || scopeValue && 'scopeValue'");
            var text = $("<span/>").addClass("dx-tab-text").attr("ng-bind", "text"),
                icon = $("<span/>").attr("ng-switch-when", "icon").addClass("dx-icon").attr("ng-class", "'dx-icon-' + icon").add(text.attr("ng-switch-when", "icon")),
                iconSrc = $("<img/>").attr("ng-switch-when", "iconSrc").addClass("dx-icon").attr("ng-src", "{{iconSrc}}").add(text.attr("ng-switch-when", "iconSrc"));
            return container.append(baseElements.html()).append(icon).append(iconSrc).append(text.attr("ng-switch-when", "text")).append(baseElements.primitive())
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxActionSheet = function() {
            return $("<div/>").attr("dx-button", "{ bindingOptions: { text: 'text', clickAction: 'clickAction', type: 'type', disabled: 'disabled' } }")
        };
        DEFAULT_ITEM_TEMPLATE_GENERATORS.dxNavBar = DEFAULT_ITEM_TEMPLATE_GENERATORS.dxTabs;
        $.extend(ui, {
            Component: NgComponent,
            registerComponent: registerNgComponent,
            Template: NgTemplate,
            TemplateProvider: NgTemplateProvider
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.widget.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            UI_FEEDBACK = "UIFeedback",
            UI_FEEDBACK_CLASS = "dx-feedback",
            ACTIVE_STATE_CLASS = "dx-state-active",
            DISABLED_STATE_CLASS = "dx-state-disabled",
            INVISIBLE_STATE_CLASS = "dx-state-invisible",
            HOVERED_STATE_CLASS = "dx-state-hovered",
            FEEDBACK_SHOW_TIMEOUT = 30,
            FEEDBACK_HIDE_TIMEOUT = 400;
        var activeElement,
            events = ui.events;
        ui.feedback = {reset: function() {
                handleEnd(true)
            }};
        ui.Widget = ui.Component.inherit({
            _defaultOptions: function() {
                return $.extend(this.callBase(), {
                        visible: true,
                        activeStateEnabled: true,
                        width: undefined,
                        height: undefined,
                        clickAction: null,
                        hoverStateEnabled: false
                    })
            },
            _init: function() {
                this.callBase();
                this._feedbackShowTimeout = FEEDBACK_SHOW_TIMEOUT;
                this._feedbackHideTimeout = FEEDBACK_HIDE_TIMEOUT
            },
            _render: function() {
                this.callBase();
                this._element().addClass("dx-widget");
                this._renderDisabledState();
                this._toggleVisibility(this.option("visible"));
                this._toggleHoverState(!this.option("disabled"));
                this._refreshFeedback();
                this._renderDimensions();
                this._renderClick()
            },
            _dispose: function() {
                this._clearTimers();
                if (activeElement && activeElement.closest(this._element()).length)
                    activeElement = null;
                this._clickAction = null;
                this.callBase()
            },
            _clean: function() {
                this.callBase();
                this._element().empty()
            },
            _clearTimers: function() {
                clearTimeout(this._feedbackHideTimer);
                clearTimeout(this._feedbackShowTimer)
            },
            _toggleVisibility: function(visible) {
                this._element().toggleClass(INVISIBLE_STATE_CLASS, !visible)
            },
            _toggleHoverState: function(value) {
                if (this.option("hoverStateEnabled"))
                    this._element().toggleClass(HOVERED_STATE_CLASS, value)
            },
            _renderDimensions: function() {
                var width = this.option("width"),
                    height = this.option("height");
                this._element().width(width);
                this._element().height(height)
            },
            _refreshFeedback: function() {
                if (this._feedbackDisabled()) {
                    this._feedbackOff();
                    this._element().removeClass(UI_FEEDBACK_CLASS)
                }
                else
                    this._element().addClass(UI_FEEDBACK_CLASS)
            },
            _renderClick: function() {
                var self = this,
                    eventName = events.addNamespace("dxclick", this.NAME);
                this._clickAction = this._createActionByOption("clickAction");
                this._clickEventContainer().off(eventName).on(eventName, function(e) {
                    self._clickAction({jQueryEvent: e})
                })
            },
            _clickEventContainer: function() {
                return this._element()
            },
            _feedbackDisabled: function() {
                return !this.option("activeStateEnabled") || this.option("disabled")
            },
            _feedbackOn: function(element, immediate) {
                if (this._feedbackDisabled())
                    return;
                this._clearTimers();
                if (immediate)
                    this._feedbackShow(element);
                else
                    this._feedbackShowTimer = window.setTimeout($.proxy(this._feedbackShow, this, element), this._feedbackShowTimeout);
                this._saveActiveElement()
            },
            _feedbackShow: function(element) {
                var activeStateElement = this._element();
                if (this._activeStateUnit)
                    activeStateElement = $(element).closest(this._activeStateUnit);
                if (!activeStateElement.hasClass(DISABLED_STATE_CLASS)) {
                    activeStateElement.addClass(ACTIVE_STATE_CLASS);
                    this._toggleHoverState(false)
                }
            },
            _saveActiveElement: function() {
                activeElement = this._element()
            },
            _feedbackOff: function(immediate) {
                this._clearTimers();
                if (immediate)
                    this._feedbackHide();
                else
                    this._feedbackHideTimer = window.setTimeout($.proxy(this._feedbackHide, this), this._feedbackHideTimeout)
            },
            _feedbackHide: function() {
                var activeStateElement = this._element();
                if (this._activeStateUnit)
                    activeStateElement = activeStateElement.find(this._activeStateUnit);
                activeStateElement.removeClass(ACTIVE_STATE_CLASS);
                this._toggleHoverState(!this.option("disabled"));
                this._clearActiveElement()
            },
            _clearActiveElement: function() {
                var rootDomElement = this._element().get(0),
                    activeDomElement = activeElement && activeElement.get(0);
                if (activeDomElement && (activeDomElement === rootDomElement || $.contains(rootDomElement, activeDomElement)))
                    activeElement = null
            },
            _optionChanged: function(name, value) {
                switch (name) {
                    case"disabled":
                        this._renderDisabledState();
                        this._refreshFeedback();
                        break;
                    case"activeStateEnabled":
                        this._refreshFeedback();
                        break;
                    case"hoverStateEnabled":
                        this._toggleHoverState();
                        break;
                    case"visible":
                        this._toggleVisibility(value);
                        break;
                    case"width":
                    case"height":
                        this._renderDimensions();
                        break;
                    case"clickAction":
                        this._renderClick();
                        break;
                    default:
                        this.callBase.apply(this, arguments)
                }
            },
            _renderDisabledState: function() {
                var disabled = this.option("disabled");
                this._element().toggleClass(DISABLED_STATE_CLASS, disabled);
                this._toggleHoverState(!disabled)
            },
            repaint: function() {
                this._refresh()
            }
        });
        var handleStart = function(args, immediate) {
                var e = args.jQueryEvent,
                    $target = args.element;
                if (events.needSkipEvent(e))
                    return;
                if (activeElement)
                    getWidget(activeElement)._feedbackOff(true);
                var closestFeedbackElement = $target.closest("." + UI_FEEDBACK_CLASS),
                    widget;
                if (closestFeedbackElement.length) {
                    widget = getWidget(closestFeedbackElement);
                    widget._feedbackOn($target, immediate);
                    if (immediate)
                        widget._feedbackOff()
                }
            };
        var handleEnd = function(immediate) {
                if (!activeElement)
                    return;
                getWidget(activeElement)._feedbackOff(immediate)
            };
        var getWidget = function(widgetElement) {
                var result;
                $.each(widgetElement.data("dxComponents"), function(index, componentName) {
                    if (ui[componentName].subclassOf(ui.Widget)) {
                        result = widgetElement.data(componentName);
                        return false
                    }
                });
                return result
            };
        $(function() {
            var startAction = new DX.Action(handleStart);
            $(document).on(events.addNamespace("dxpointerdown", UI_FEEDBACK), function(e) {
                startAction.execute({
                    jQueryEvent: e,
                    element: $(e.target)
                })
            }).on(events.addNamespace("dxpointerup dxpointercancel", UI_FEEDBACK), function(e) {
                var activeElementClicked = activeElement && $(e.target).closest("." + UI_FEEDBACK_CLASS).get(0) === activeElement.get(0);
                if (activeElementClicked)
                    startAction.execute({
                        jQueryEvent: e,
                        element: $(e.target)
                    }, true);
                handleEnd()
            })
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.containerWidget.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            ANONYMOUS_TEMPLATE_NAME = "template",
            TEMPLATE_SELECTOR = "[data-options]",
            TEMPLATES_DATA_KEY = "dxTemplates";
        var getTemplateOptions = function(element) {
                var options = $(element).data("options");
                if ($.trim(options).charAt(0) !== "{")
                    options = "{" + options + "}";
                return new Function("return " + options)().dxTemplate
            };
        var ContainerWidget = ui.Widget.inherit({
                _defaultOptions: function() {
                    return $.extend(this.callBase(), {contentReadyAction: $.noop})
                },
                _init: function() {
                    this.callBase();
                    this._templateProvider = new ui.TemplateProvider;
                    this._initTemplates();
                    this._initContentReadyAction()
                },
                _clean: $.noop,
                _createTemplate: function(element) {
                    return new(this._templateProvider.getTemplateClass(this))(element)
                },
                _initTemplates: function() {
                    var self = this,
                        templates = {},
                        dataTemplateElements = this._element().data(TEMPLATES_DATA_KEY),
                        templateElements = dataTemplateElements ? dataTemplateElements : this._element().contents().filter(TEMPLATE_SELECTOR);
                    if (templateElements.length)
                        templateElements.each(function() {
                            var templateOptions = getTemplateOptions(this);
                            if (!templateOptions.name)
                                throw Error("Template name was not specified");
                            templates[templateOptions.name] = self._createTemplate(this)
                        });
                    else
                        templates[ANONYMOUS_TEMPLATE_NAME] = self._createTemplate(self._element().contents());
                    this._templates = templates
                },
                _initContentReadyAction: function() {
                    this._contentReadyAction = this._createActionByOption("contentReadyAction", {excludeValidators: ["gesture", "designMode", "disabled"]})
                },
                _render: function() {
                    this.callBase();
                    this._renderContent()
                },
                _renderContent: function() {
                    this._renderContentImpl();
                    this._fireContentReadyAction()
                },
                _renderContentImpl: DX.abstract,
                _fireContentReadyAction: function() {
                    this._contentReadyAction({excludeValidators: ["disabled", "gesture"]})
                },
                _getTemplate: function(templateName) {
                    var result = this._acquireTemplate.apply(this, arguments);
                    if (!result && this._templateProvider.supportDefaultTemplate(this)) {
                        result = this._templateProvider.getDefaultTemplate(this);
                        if (!result)
                            throw Error(DX.utils.stringFormat("Template \"{0}\" was not found and no default template specified!", templateName));
                    }
                    return result
                },
                _acquireTemplate: function(templateSource) {
                    if (!templateSource)
                        return templateSource;
                    if (templateSource.nodeType || templateSource.jquery) {
                        templateSource = $(templateSource);
                        if (templateSource.is("script"))
                            templateSource = templateSource.html();
                        return this._createTemplate(templateSource)
                    }
                    if (typeof templateSource === "string")
                        return this._templates[templateSource];
                    if ($.isFunction(templateSource)) {
                        var args = $.makeArray(arguments).slice(1);
                        return this._acquireTemplate(templateSource.apply(this, args))
                    }
                },
                _optionChanged: function(name) {
                    switch (name) {
                        case"contentReadyAction":
                            this._initContentReadyAction();
                            break;
                        default:
                            this.callBase.apply(this, arguments)
                    }
                },
                _cleanTemplates: function() {
                    $.each(this._templates, function(templateName, template) {
                        template.dispose()
                    })
                },
                _dispose: function() {
                    this._cleanTemplates();
                    this._contentReadyAction = null;
                    this.callBase()
                },
                addTemplate: function(template) {
                    $.extend(this._templates, template)
                }
            });
        ui.ContainerWidget = ContainerWidget
    })(jQuery, DevExpress);
    /*! Module core, file ui.template.js */
    (function($, DX, undefined) {
        var isString = DX.utils.isString;
        var currentTemplateEngine;
        var templateEngines = [];
        var BaseTemplate = DevExpress.Class.inherit({
                _compile: function(html, element) {
                    return element
                },
                _render: function(template, data) {
                    return template
                },
                ctor: function(element) {
                    this._element = $(element);
                    if (this._element.length === 1) {
                        if (this._element[0].nodeName.toLowerCase() !== "script")
                            this._element = $("<div />").append(this._element);
                        this._template = this._compile(this._element.html() || "", this._element)
                    }
                },
                render: function(container, data) {
                    var result;
                    if (this._template) {
                        result = this._render(this._template, data);
                        if (isString(result))
                            result = $.parseHTML(result);
                        result = $(result);
                        if (container)
                            container.append(result);
                        return result
                    }
                },
                dispose: $.noop
            });
        var createTemplateEngine = function(options) {
                if (options && options.compile && options.render)
                    return BaseTemplate.inherit({
                            allowRenderToDetachedContainer: options.allowRenderToDetachedContainer !== false,
                            _compile: options.compile,
                            _render: options.render
                        });
                else
                    throw Error("Template Engine must contains compile and render methods");
            };
        if (window.ko) {
            var koCustomTemplateEngine = function(){};
            koCustomTemplateEngine.prototype = ko.utils.extend(new ko.templateEngine, {
                renderTemplateSource: function(templateSource, bindingContext, options) {
                    var precompiledTemplate = templateSource["data"]("precompiledTemplate");
                    if (!precompiledTemplate) {
                        precompiledTemplate = new currentTemplateEngine(templateSource.domElement);
                        templateSource["data"]("precompiledTemplate", precompiledTemplate)
                    }
                    return precompiledTemplate.render(null, bindingContext.$data)
                },
                allowTemplateRewriting: false
            })
        }
        DevExpress.ui.setTemplateEngine = function(templateEngine) {
            if (isString(templateEngine)) {
                currentTemplateEngine = templateEngines && templateEngines[templateEngine];
                if (!currentTemplateEngine && templateEngine !== "default")
                    throw Error(DX.utils.stringFormat("Template Engine \"{0}\" is not supported", templateEngine));
            }
            else
                currentTemplateEngine = createTemplateEngine(templateEngine) || currentTemplateEngine;
            if (window.ko)
                ko.setTemplateEngine(currentTemplateEngine ? new koCustomTemplateEngine : new ko.nativeTemplateEngine)
        };
        DevExpress.ui.TemplateProvider = DevExpress.ui.TemplateProvider.inherit({getTemplateClass: function() {
                if (currentTemplateEngine)
                    return currentTemplateEngine;
                return this.callBase.apply(this, arguments)
            }});
        var registerTemplateEngine = function(name, templateOptions) {
                templateEngines[name] = createTemplateEngine(templateOptions)
            };
        registerTemplateEngine("jquery-tmpl", {
            compile: function(html, element) {
                return element
            },
            render: function(template, data) {
                return template.tmpl(data)
            }
        });
        registerTemplateEngine("jsrender", {
            compile: function(html) {
                return $.templates(html)
            },
            render: function(template, data) {
                return template.render(data)
            }
        });
        registerTemplateEngine("mustache", {
            compile: function(html) {
                return Mustache.compile(html)
            },
            render: function(template, data) {
                return template(data)
            }
        });
        registerTemplateEngine("hogan", {
            compile: function(html) {
                return Hogan.compile(html)
            },
            render: function(template, data) {
                return template.render(data)
            }
        });
        registerTemplateEngine("underscore", {
            compile: function(html) {
                return _.template(html)
            },
            render: function(template, data) {
                return template(data)
            }
        });
        registerTemplateEngine("handlebars", {
            compile: function(html) {
                return Handlebars.compile(html)
            },
            render: function(template, data) {
                return template(data)
            }
        });
        registerTemplateEngine("doT", {
            compile: function(html) {
                return doT.template(html)
            },
            render: function(template, data) {
                return template(data)
            }
        })
    })(jQuery, DevExpress);
    /*! Module core, file ui.collectionContainerWidget.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            events = ui.events;
        var CollectionContainerWidget = ui.ContainerWidget.inherit({
                _defaultOptions: function() {
                    return $.extend(this.callBase(), {
                            items: [],
                            itemTemplate: "item",
                            itemRender: null,
                            itemClickAction: null,
                            itemRenderedAction: null,
                            noDataText: Globalize.localize("dxCollectionContainerWidget-noDataText"),
                            dataSource: null
                        })
                },
                _init: function() {
                    this.callBase();
                    this._cleanRenderedItems();
                    this._refreshDataSource()
                },
                _dataSourceOptions: function() {
                    var options = {
                            paginate: false,
                            _preferSync: false
                        };
                    if ($.isArray(this.option("dataSource")))
                        options._preferSync = true;
                    return options
                },
                _cleanRenderedItems: function() {
                    this._renderedItemsCount = 0
                },
                _optionChanged: function(name, value, prevValue) {
                    switch (name) {
                        case"items":
                            this._cleanRenderedItems();
                            this._invalidate();
                            this.callBase.apply(this, arguments);
                            return;
                        case"dataSource":
                            this._refreshDataSource();
                            if (!this._dataSource)
                                this.option("items", []);
                            return;
                        case"noDataText":
                            this._renderEmptyMessage();
                            return;
                        case"itemRenderedAction":
                            this._createItemRenderAction();
                            return;
                        case"itemTemplate":
                            this._itemTemplateName = null;
                            this._invalidate();
                        case"itemRender":
                            this._itemRender = null;
                            this._invalidate();
                        default:
                            this.callBase(name, value, prevValue)
                    }
                },
                _expectNextPageLoading: function() {
                    this._isNextPageLoading = true
                },
                _forgetNextPageLoading: function() {
                    this._isNextPageLoading = false
                },
                _handleDataSourceChanged: function(newItems) {
                    var items = this.option("items");
                    if (this._initialized && items && this._shouldAppendItems()) {
                        this._renderedItemsCount = items.length;
                        this.option().items = items.concat(newItems);
                        this._renderContent()
                    }
                    else
                        this.option("items", newItems);
                    this._forgetNextPageLoading()
                },
                _handleDataSourceLoadError: function() {
                    this._forgetNextPageLoading()
                },
                _shouldAppendItems: function() {
                    return this._isNextPageLoading && this._allowDinamicItemsAppend()
                },
                _allowDinamicItemsAppend: function() {
                    return false
                },
                _clean: function() {
                    this._itemContainer().empty()
                },
                _refresh: function() {
                    this._cleanRenderedItems();
                    this.callBase.apply(this, arguments)
                },
                _itemContainer: function() {
                    return this._element()
                },
                _itemClass: DX.abstract,
                _itemSelector: function() {
                    return "." + this._itemClass()
                },
                _itemDataKey: DX.abstract,
                _itemElements: function() {
                    return this._itemContainer().find(this._itemSelector())
                },
                _render: function() {
                    this.callBase();
                    this._attachClickEvent()
                },
                _attachClickEvent: function() {
                    var itemSelector = this._itemSelector(),
                        eventName = events.addNamespace("dxclick", this.NAME + "Click");
                    this._itemContainer().off(eventName, itemSelector).on(eventName, itemSelector, $.proxy(this._handleItemClick, this))
                },
                _handleItemClick: function(e) {
                    this._handleItemJQueryEvent(e, "itemClickAction")
                },
                _renderContentImpl: function() {
                    var items = this.option("items") || [];
                    if (this._renderedItemsCount)
                        this._renderItems(items.slice(this._renderedItemsCount));
                    else
                        this._renderItems(items)
                },
                _renderItems: function(items) {
                    if (items.length)
                        $.each(items, $.proxy(this._renderItem, this));
                    this._renderEmptyMessage()
                },
                _renderItem: function(index, item, container) {
                    container = container || this._itemContainer();
                    var itemRenderer = this._getItemRenderer(),
                        itemTemplateName = this._getItemTemplateName(),
                        itemTemplate = this._getTemplate(item.template || itemTemplateName, index, item),
                        itemElement,
                        renderArgs = {
                            index: index,
                            item: item,
                            container: container
                        };
                    if (itemRenderer)
                        itemElement = this._createItemByRenderer(itemRenderer, renderArgs);
                    else if (itemTemplate)
                        itemElement = this._createItemByTemplate(itemTemplate, renderArgs);
                    else
                        itemElement = this._createItemByRenderer(this._itemRenderDefault, renderArgs);
                    itemElement.addClass(this._itemClass()).data(this._itemDataKey(), item);
                    var postprocessRenderArgs = {
                            itemElement: itemElement,
                            itemData: item,
                            itemIndex: index
                        };
                    this._postprocessRenderItem(postprocessRenderArgs);
                    this._getItemRenderAction()({
                        itemElement: itemElement,
                        itemData: item
                    });
                    return itemElement
                },
                _createItemRenderAction: function() {
                    return this._itemRenderAction = this._createActionByOption("itemRenderedAction", {
                            element: this._element(),
                            excludeValidators: ["gesture", "designMode", "disabled"]
                        })
                },
                _getItemRenderAction: function() {
                    return this._itemRenderAction || this._createItemRenderAction()
                },
                _getItemRenderer: function() {
                    this._itemRender = this._itemRender || this.option("itemRender");
                    return this._itemRender
                },
                _createItemByRenderer: function(itemRenderer, renderArgs) {
                    var itemElement = $("<div />").appendTo(renderArgs.container);
                    var rendererResult = itemRenderer.call(this, renderArgs.item, renderArgs.index, itemElement);
                    if (rendererResult && itemElement[0] !== rendererResult[0])
                        itemElement.append(rendererResult);
                    return itemElement
                },
                _getItemTemplateName: function() {
                    this._itemTemplateName = this._itemTemplateName || this.option("itemTemplate");
                    return this._itemTemplateName
                },
                _createItemByTemplate: function(itemTemplate, renderArgs) {
                    return itemTemplate.render(renderArgs.container, renderArgs.item, renderArgs.index, "ignoreTarget")
                },
                _itemRenderDefault: function(item, index, itemElement) {
                    if ($.isPlainObject(item)) {
                        if (item.visible !== undefined && !item.visible)
                            itemElement.hide();
                        if (item.disabled)
                            itemElement.addClass("dx-state-disabled");
                        if (item.text)
                            itemElement.text(item.text);
                        if (item.html)
                            itemElement.html(item.html)
                    }
                    else
                        itemElement.html(String(item))
                },
                _postprocessRenderItem: $.noop,
                _renderEmptyMessage: function() {
                    var noDataText = this.option("noDataText"),
                        noDataTextElement = this._element().find(".dx-empty-message"),
                        items = this.option("items"),
                        itemExists = items && items.length;
                    if (!noDataText || itemExists || this._dataSource && this._dataSource.isLoading())
                        noDataTextElement.remove();
                    else {
                        if (!noDataTextElement.length)
                            noDataTextElement = $("<div />").addClass("dx-empty-message").appendTo(this._itemContainer());
                        noDataTextElement.text(noDataText)
                    }
                },
                _handleItemJQueryEvent: function(jQueryEvent, handlerOptionName, actionArgs, actionConfig) {
                    this._handleItemEvent(jQueryEvent.target, handlerOptionName, $.extend(actionArgs, {jQueryEvent: jQueryEvent}), actionConfig)
                },
                _closestItemElement: function($element) {
                    return $($element).closest(this._itemSelector())
                },
                _handleItemEvent: function(initiator, handlerOptionName, actionArgs, actionConfig) {
                    var $itemElement = this._closestItemElement($(initiator)),
                        action = this._createActionByOption(handlerOptionName, actionConfig);
                    actionArgs = $.extend({
                        itemElement: $itemElement,
                        itemData: this._getItemData($itemElement)
                    }, actionArgs);
                    return action(actionArgs)
                },
                _getItemData: function($itemElement) {
                    return $itemElement.data(this._itemDataKey())
                }
            }).include(ui.DataHelperMixin);
        ui.CollectionContainerWidget = CollectionContainerWidget
    })(jQuery, DevExpress);
    /*! Module core, file ui.selectableCollectionWidget.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            events = ui.events;
        var SelectableCollectionWidget = ui.CollectionContainerWidget.inherit({
                _defaultOptions: function() {
                    return $.extend(this.callBase(), {
                            selectedIndex: -1,
                            itemSelectAction: null
                        })
                },
                _render: function() {
                    this.callBase();
                    this._renderSelectedIndex(this.option("selectedIndex"));
                    this._attachSelectedEvent()
                },
                _attachSelectedEvent: $.noop,
                _handleItemSelect: function(args) {
                    var e = args.jQueryEvent,
                        instance = args.component;
                    if (events.needSkipEvent(e))
                        return;
                    var itemElements = instance._itemElements(),
                        selectedItemElement = $(e.target).closest(instance._itemSelector()),
                        selectedItemIndex = itemElements.index(selectedItemElement);
                    if (instance.option("selectedIndex") !== selectedItemIndex)
                        instance._onItemSelectAction(selectedItemIndex)
                },
                _onItemSelectAction: function(newIndex) {
                    this.option("selectedIndex", newIndex)
                },
                _renderSelectedIndex: DX.abstract,
                _renderEmptyMessage: $.noop,
                _optionChanged: function(name, value, prevValue) {
                    if (name === "selectedIndex") {
                        this._renderSelectedIndex(value, prevValue);
                        this._handleItemEvent(this._selectedItemElement(value), "itemSelectAction", null)
                    }
                    else
                        this.callBase.apply(this, arguments)
                },
                _selectedItemElement: function(index) {
                    return this._itemElements().eq(index)
                }
            });
        ui.SelectableCollectionWidget = SelectableCollectionWidget
    })(jQuery, DevExpress);
    /*! Module core, file ui.optionsByDevice.js */
    (function($, DX, undefined) {
        var isSimulationMode = function(device) {
                var realDevice = DX.devices.real,
                    isOldAndroid = realDevice.platform === "android" && realDevice.version.length && realDevice.version[0] < 4,
                    isPlatformForced = realDevice.platform !== device.platform,
                    isForcedGeneric = device.platform === "generic",
                    isForcedDesktop = device.platform === "desktop",
                    isTizen = realDevice.platform === "tizen",
                    isGeneric = realDevice.platform === "generic",
                    isRippleEmulator = DX.devices.isRippleEmulator(),
                    isSimulator = window.top !== window.self && window.top["dx-force-device"];
                return isOldAndroid || isTizen || isRippleEmulator || isSimulator || isPlatformForced && !isForcedGeneric && !(isGeneric && isForcedDesktop)
            };
        var optionConfigurator = {};
        optionConfigurator.dxActionSheet = function(device) {
            if (device.platform === "ios" && device.tablet)
                return {usePopover: true}
        };
        optionConfigurator.dxScrollable = function(device) {
            if (isSimulationMode(device))
                return {
                        useNative: false,
                        useSimulatedScrollBar: true
                    };
            else if (device.platform === "android" || device.platform === "win8" && device.phone)
                return {useSimulatedScrollBar: true}
        };
        optionConfigurator.dxScrollView = function(device) {
            var result = optionConfigurator.dxScrollable(device) || {};
            var realDevice = DevExpress.devices.real;
            if (realDevice.platform === "ios" || device.platform === "desktop" || device.platform === "generic")
                $.extend(result, {refreshStrategy: "pullDown"});
            if (realDevice.platform === "android")
                $.extend(result, {refreshStrategy: "swipeDown"});
            if (realDevice.platform === "win8")
                $.extend(result, {
                    refreshStrategy: "slideDown",
                    useSimulatedScrollBar: device.phone
                });
            return result
        };
        optionConfigurator.dxList = function(device) {
            var result = optionConfigurator.dxScrollable(device) || {};
            if (device.platform === "desktop")
                $.extend(result, {
                    showScrollbar: false,
                    showNextButton: true,
                    autoPagingEnabled: false,
                    editConfig: {selectionMode: "control"}
                });
            if (device.platform === "ios")
                $.extend(result, {editConfig: {deleteMode: device.version == 7 ? "slideItem" : "slideButton"}});
            if (device.platform === "android")
                $.extend(result, {editConfig: {deleteMode: "swipe"}});
            if (device.platform === "win8")
                $.extend(result, {editConfig: {deleteMode: "hold"}});
            if (device.platform === "generic")
                $.extend(result, {editConfig: {deleteMode: "slideItem"}});
            return result
        };
        optionConfigurator.dxPopup = function(device) {
            if (device.platform === "win8" && !device.phone)
                return {
                        width: "60%",
                        height: "auto"
                    };
            if (device.platform === "win8" && device.phone)
                return {position: {
                            my: "top center",
                            at: "top center",
                            of: window,
                            offset: "0 20"
                        }};
            if (device.platform === "ios")
                return {animation: {
                            show: {
                                type: "slide",
                                duration: 400,
                                from: {
                                    top: $("body").height(),
                                    opacity: 1
                                },
                                to: {
                                    top: 0,
                                    opacity: 1
                                }
                            },
                            hide: {
                                type: "slide",
                                duration: 400,
                                from: {
                                    top: 0,
                                    opacity: 1
                                },
                                to: {
                                    top: $("body").height(),
                                    opacity: 1
                                }
                            }
                        }}
        };
        optionConfigurator.dxDialog = function(device) {
            if (device.platform === "ios")
                return {width: 276};
            if (device.platform === "win8" && !device.phone)
                return {width: "60%"};
            if (device.platform === "android")
                return {
                        lWidth: "60%",
                        pWidth: "80%"
                    }
        };
        optionConfigurator.dxLookup = function(device) {
            if (device.platform === "android")
                return {hideCancelButton: false};
            if (device.platform === "win8" && device.phone)
                return {
                        showCancelButton: false,
                        fullScreen: true
                    };
            if (device.platform === "ios" && device.phone)
                return {fullScreen: true};
            if (device.platform === "ios" && device.tablet)
                return {usePopover: true}
        };
        optionConfigurator.dxLoadIndicator = function(device) {
            if (DevExpress.browser.msie && DevExpress.browser.version[0] <= 10)
                return {viaImage: true}
        };
        optionConfigurator.dxDatePicker = function(device) {
            if (device.platform !== "win8")
                return {
                        width: 333,
                        height: 280
                    };
            else
                return {showNames: true}
        };
        optionConfigurator.dxDateBox = function(device) {
            if (device.android || device.win8)
                return {useNativePicker: false}
        };
        optionConfigurator.dxDropDownMenu = function(device) {
            if (device.platform === "ios")
                return {usePopover: true}
        };
        optionConfigurator.dxToast = function(device) {
            if (device.platform === "win8")
                return {
                        position: {
                            my: "top center",
                            at: "top center",
                            of: window,
                            offset: "0 0"
                        },
                        width: function() {
                            return $(window).width()
                        },
                        heigth: "35px"
                    }
        };
        optionConfigurator.dxToolbar = function(device) {
            if (device.platform === "ios")
                return {submenuType: "dxActionSheet"};
            if (device.platform === "win8")
                return {submenuType: "dxList"};
            if (device.platform === "android")
                return {submenuType: "dxDropDownMenu"}
        };
        DX.ui.optionsByDevice = function(device, componentName) {
            var configurator = optionConfigurator[componentName];
            return configurator && configurator(device)
        }
    })(jQuery, DevExpress)
}
if (!DevExpress.MOD_VIZ_CORE) {
    if (!window.DevExpress)
        throw Error('Required module is not referenced: core');
    /*! Module viz-core, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz = {}
    })(DevExpress);
    /*! Module viz-core, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz.core = {}
    })(DevExpress);
    /*! Module viz-core, file tickProvider.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            math = Math,
            core = DX.viz.core;
        var TICKS_COUNT_LIMIT = 2000;
        core.outOfScreen = {
            x: -1000,
            y: -1000
        };
        core.tickIntervalCalculator = {
            _defaultNumberMultipliers: [1, 2, 3, 5],
            _defaultGridSpacingFactor: 30,
            _getCommonTickInterval: function(deltaCoef, numberMultipliers) {
                var factor,
                    result = 0,
                    hasResult = false,
                    i;
                for (factor = 1; !hasResult; factor *= 10)
                    for (i = 0; i < numberMultipliers.length; i++) {
                        result = numberMultipliers[i] * factor;
                        if (deltaCoef <= result) {
                            hasResult = true;
                            break
                        }
                    }
                return result
            },
            _getNumericTickInterval: function(deltaCoef, numberMultipliers) {
                var factor,
                    result = 0,
                    newResult,
                    hasResult = false,
                    i;
                if (deltaCoef > 1.0)
                    result = this._getCommonTickInterval(deltaCoef, numberMultipliers);
                else if (deltaCoef > 0) {
                    result = 1;
                    for (factor = 0.1; !hasResult; factor /= 10)
                        for (i = numberMultipliers.length - 1; i >= 0; i--) {
                            newResult = numberMultipliers[i] * factor;
                            if (deltaCoef > newResult) {
                                hasResult = true;
                                break
                            }
                            result = newResult
                        }
                }
                return utils.adjustValue(result)
            },
            _getLogarithmicTickInterval: function(deltaCoef, numberMultipliers) {
                var result = 0;
                if (deltaCoef !== 0)
                    result = this._getCommonTickInterval(deltaCoef, numberMultipliers);
                return utils.adjustValue(result)
            },
            _getDateTimeTickInterval: function(deltaCoef, numberMultipliers) {
                var dateTimeMultipliers = {
                        millisecond: [1, 2, 5, 10, 25, 100, 250, 300, 500],
                        second: [1, 2, 3, 5, 10, 15, 20, 30],
                        minute: [1, 2, 3, 5, 10, 15, 20, 30],
                        hour: [1, 2, 3, 4, 6, 8, 12],
                        day: [1, 2, 3, 5, 7, 10, 14],
                        month: [1, 2, 3, 6]
                    },
                    result = {},
                    factor,
                    key,
                    specificMultipliers,
                    yearsCount,
                    i;
                if (deltaCoef < 1.0)
                    return {milliseconds: 1};
                for (key in dateTimeMultipliers)
                    if (dateTimeMultipliers.hasOwnProperty(key)) {
                        specificMultipliers = dateTimeMultipliers[key];
                        for (i = 0; i < specificMultipliers.length; i++)
                            if (deltaCoef <= utils.convertDateUnitToMilliseconds(key, specificMultipliers[i])) {
                                result[key + 's'] = specificMultipliers[i];
                                return result
                            }
                    }
                for (factor = 1; ; factor *= 10)
                    for (i = 0; i < numberMultipliers.length; i++) {
                        yearsCount = factor * numberMultipliers[i];
                        if (deltaCoef <= utils.convertDateUnitToMilliseconds('year', yearsCount))
                            return {years: yearsCount}
                    }
                return null
            },
            getTickInterval: function(options) {
                var self = this,
                    gridSpacingFactor = options.gridSpacingFactor || self._defaultGridSpacingFactor,
                    numberMultipliers,
                    deltaCoef,
                    businessDelta = options.businessDelta;
                numberMultipliers = options.numberMultipliers || self._defaultNumberMultipliers;
                self._testNumberMultipliers = numberMultipliers;
                if (options.type === 'logarithmic')
                    businessDelta = Math.round(Math.abs(utils.getLog(options.max, options.base) - utils.getLog(options.min, options.base)));
                deltaCoef = options.screenDelta > 0 ? gridSpacingFactor * businessDelta / options.screenDelta : 0;
                switch (options.type) {
                    case'numeric':
                        return self._getNumericTickInterval(deltaCoef, numberMultipliers);
                        break;
                    case'datetime':
                        return self._getDateTimeTickInterval(deltaCoef, numberMultipliers);
                        break;
                    case'logarithmic':
                        return self._getLogarithmicTickInterval(deltaCoef, numberMultipliers);
                        break
                }
                return null
            }
        };
        core.minorTickIntervalCalculator = {
            _defaultNumberMultipliers: [2, 4, 5, 8, 10],
            _defaultGridSpacingFactor: 15,
            _getDateTimeTickInterval: function(businessDelta, deltaCoef, numberMultipliers) {
                var result,
                    i;
                for (i = numberMultipliers.length - 1; i >= 0; i--) {
                    this.testResultNumberMultiplier = numberMultipliers[i];
                    result = Math.floor(businessDelta / numberMultipliers[i]);
                    if (deltaCoef <= result)
                        return utils.convertMillisecondsToDateUnits(result)
                }
                return 0
            },
            _getNumericTickInterval: function(businessDelta, deltaCoef, numberMultipliers) {
                var result,
                    i;
                for (i = numberMultipliers.length - 1; i >= 0; i--) {
                    this.testResultNumberMultiplier = numberMultipliers[i];
                    result = businessDelta / numberMultipliers[i];
                    if (deltaCoef <= result)
                        return utils.adjustValue(result)
                }
                return 0
            },
            getTickInterval: function(type, businessDelta, screenDelta, gridSpacingFactor, numberMultipliers) {
                var self = this,
                    gridSpacingFactor = !utils.isDefined(gridSpacingFactor) ? self._defaultGridSpacingFactor : gridSpacingFactor,
                    numberMultipliers = numberMultipliers || self._defaultNumberMultipliers,
                    deltaCoef = gridSpacingFactor * businessDelta / screenDelta;
                switch (type) {
                    case'numeric':
                        return self._getNumericTickInterval(businessDelta, deltaCoef, numberMultipliers);
                    case'datetime':
                        return self._getDateTimeTickInterval(businessDelta, deltaCoef, numberMultipliers)
                }
                return 0
            }
        };
        core.tickProvider = {
            _appendFakeSVGElement: function(value, text, options) {
                var textOptions = $.extend({}, options.textOptions, {rotate: 0});
                return options.renderer.createText(text, core.outOfScreen.x + options.translator.translateX(value), core.outOfScreen.y, textOptions).append()
            },
            _getDistanceByAngle: function(elementHeight, rotationAngle) {
                return elementHeight / Math.abs(Math.sin(rotationAngle * (Math.PI / 180)))
            },
            _areDisplayValuesValid: function(value1, value2, options) {
                var self = this,
                    getText = self._getTextFunc(options),
                    rotationAngle = options.textOptions && utils.isNumber(options.textOptions.rotate) ? options.textOptions.rotate : 0,
                    svgElement1 = self._appendFakeSVGElement(value1, getText(value1), options),
                    svgElement2 = self._appendFakeSVGElement(value2, getText(value2), options),
                    bBox1 = svgElement1.getBBox(),
                    bBox2 = svgElement2.getBBox(),
                    result,
                    inverted = options.translator.businessRange.invertX;
                if (rotationAngle !== 0)
                    result = self._getDistanceByAngle(bBox1.height, rotationAngle) <= Math.abs(bBox2.x - bBox1.x);
                else
                    result = !inverted ? bBox1.x + bBox1.width < bBox2.x : bBox2.x + bBox2.width < bBox1.x;
                svgElement1.remove();
                svgElement2.remove();
                return result
            },
            _removeInvalidDatesWithUnitBegining: function(dates, options) {
                if (dates.length <= 1 || !options.setTicksAtUnitBeginning || !utils.isDate(options.min))
                    return;
                if (!this._areDisplayValuesValid(dates[0], dates[1], options))
                    dates.splice(1, 1)
            },
            _getMaxDisplayValue: function(values, options) {
                var maxDisplayValue = null,
                    getText = this._getTextFunc(options),
                    currentDisplayValue,
                    i;
                maxDisplayValue = getText(values[0]);
                if (!options.isRotate)
                    for (i = 1; i < values.length; i++) {
                        currentDisplayValue = getText(values[i]);
                        if (maxDisplayValue.length < currentDisplayValue.length)
                            maxDisplayValue = currentDisplayValue
                    }
                return maxDisplayValue
            },
            _getValueSize: function(values, options) {
                var self = this,
                    value,
                    rotationAngle = options.textOptions ? options.textOptions.rotate : 0,
                    svgElement,
                    bBox,
                    result;
                if (values.length === 0)
                    return 0;
                options.isRotate = utils.isNumber(rotationAngle) && rotationAngle !== 0;
                value = self._getMaxDisplayValue(values, options);
                svgElement = self._appendFakeSVGElement(value, value, options);
                bBox = svgElement.getBBox();
                if (options.isRotate)
                    result = self._getDistanceByAngle(bBox.height, rotationAngle);
                else
                    result = options.isHorizontal ? bBox.width : bBox.height;
                svgElement.remove();
                return Math.ceil(result)
            },
            _adjustNumericTickValue: function(value, interval, min) {
                return utils.isExponential(value) ? utils.adjustValue(value) : utils.applyPrecisionByMinDelta(min, interval, value)
            },
            _generateStartTick: function(tickInterval, options) {
                var self = this,
                    milliseconds = 0,
                    boundedRule = options.min - options.max < 0,
                    startTick = options.min,
                    isDate = utils.isDate(options.min),
                    currentTickInterval = isDate ? utils.convertDateTickIntervalToMilliseconds(tickInterval) : tickInterval,
                    nextTick;
                if (options.type === 'logarithmic')
                    startTick = utils.raiseTo(Math.floor(utils.adjustValue(utils.getLog(options.min, options.base)) / currentTickInterval * currentTickInterval), options.base);
                else {
                    startTick = Math.floor(options.min / currentTickInterval) * currentTickInterval;
                    startTick = isDate ? new Date(startTick) : startTick;
                    startTick = isDate ? new Date(startTick) : self._adjustNumericTickValue(startTick, currentTickInterval, options.min);
                    while (boundedRule === startTick - options.min < 0 && startTick !== options.min) {
                        nextTick = self._nextTick(startTick, tickInterval, options);
                        if (nextTick !== startTick)
                            startTick = nextTick;
                        else
                            return nextTick
                    }
                }
                return startTick
            },
            _nextTick: function(tick, tickInterval, options) {
                var nextTick,
                    lgPower,
                    self = this;
                if (options.type === 'logarithmic') {
                    lgPower = utils.addInterval(utils.adjustValue(utils.getLog(tick, options.base)), tickInterval, options.min > options.max);
                    nextTick = utils.raiseTo(lgPower, options.base)
                }
                else {
                    nextTick = utils.addInterval(tick, tickInterval, options.min > options.max);
                    if (options.type === 'numeric')
                        nextTick = utils.isExponential(nextTick) ? utils.adjustValue(nextTick) : utils.applyPrecisionByMinDelta(options.min, tickInterval, nextTick);
                    if (options.type === 'datetime' && options.setTicksAtUnitBeginning)
                        utils.correctDateWithUnitBeginning(nextTick, tickInterval)
                }
                return nextTick
            },
            _addMinorTicks: function(majorTick1, majorTick2, ticksInfo, options, isReverse) {
                var self = this,
                    i,
                    dataType = utils.isDate(majorTick1) ? 'datetime' : 'numeric',
                    businessDelta,
                    minorTicks = [],
                    interval = 0,
                    minorTickIntervalsCount = options.minorTickCount + 1,
                    intervalsCount,
                    tickInterval;
                options.min = majorTick1;
                options.max = majorTick2;
                if (!utils.isDefined(options.tickInterval)) {
                    businessDelta = Math.abs(options.max - options.min);
                    if (utils.isDefined(options.minorTickCount)) {
                        if (!ticksInfo.majorTicks.autoArrangementStep || ticksInfo.majorTicks.autoArrangementStep <= 1) {
                            intervalsCount = options.minorTickCount + 1;
                            interval = dataType === 'datetime' ? utils.convertDateTickIntervalToMilliseconds(ticksInfo.majorTickInterval) : ticksInfo.majorTickInterval;
                            minorTickIntervalsCount = Math.round(businessDelta / interval * intervalsCount) || 1
                        }
                        tickInterval = dataType === 'datetime' ? utils.convertMillisecondsToDateUnits(businessDelta / minorTickIntervalsCount) : businessDelta / minorTickIntervalsCount;
                        if ($.isNumeric(tickInterval))
                            tickInterval = utils.adjustValue(tickInterval)
                    }
                    else if (utils.isDate(majorTick1))
                        tickInterval = core.minorTickIntervalCalculator.getTickInterval(dataType, businessDelta, businessDelta * options.deltaCoef, options.gridSpacingFactor, options.numberMultipliers)
                }
                options = $.extend(true, {}, options, {tickInterval: tickInterval});
                minorTicks = self.getTicks(options);
                if (isReverse)
                    minorTicks.reverse();
                if (minorTicks.length > 0)
                    if (Math.ceil(Math.abs(majorTick2 - minorTicks[minorTicks.length - 1]) * options.deltaCoef) < 2)
                        minorTicks.pop();
                for (i = 0; i < minorTicks.length; i++) {
                    ticksInfo.minorTicks.push(minorTicks[i]);
                    ticksInfo.fullTicks.push(minorTicks[i])
                }
            },
            _addLeftBoudedTicks: function(ticksInfo, min, minorTicksOptions) {
                if (utils.isDefined(min) && ticksInfo.majorTicks[0].valueOf() !== min.valueOf()) {
                    minorTicksOptions.addMinMax.max = true;
                    this._addMinorTicks(ticksInfo.majorTicks[0], min, ticksInfo, minorTicksOptions, true);
                    minorTicksOptions.addMinMax.max = false;
                    if (minorTicksOptions.showCustomBoundaryTicks) {
                        if (ticksInfo.minorTicks.length > 0 && ticksInfo.minorTicks[0].valueOf() === min.valueOf())
                            ticksInfo.minorTicks.shift(min);
                        ticksInfo.customBoundaryTicks.push(min);
                        ticksInfo.fullTicks.unshift(min)
                    }
                }
            },
            _addRightBoudedTicks: function(ticksInfo, max, minorTicksOptions) {
                var lastMajorTick = ticksInfo.majorTicks[ticksInfo.majorTicks.length - 1];
                ticksInfo.fullTicks.push(lastMajorTick);
                if (utils.isDefined(max) && lastMajorTick.valueOf() !== max.valueOf()) {
                    minorTicksOptions.addMinMax.min = false;
                    minorTicksOptions.addMinMax.max = true;
                    this._addMinorTicks(lastMajorTick, max, ticksInfo, minorTicksOptions);
                    if (minorTicksOptions.showCustomBoundaryTicks) {
                        if (ticksInfo.minorTicks.length > 0 && ticksInfo.minorTicks[ticksInfo.minorTicks.length - 1].valueOf() === max.valueOf())
                            ticksInfo.minorTicks.pop(max);
                        ticksInfo.customBoundaryTicks.push(max);
                        ticksInfo.fullTicks.push(max)
                    }
                }
            },
            _correctBoundedTicks: function(min, max, ticks, addMinMax) {
                addMinMax = $.extend({}, {
                    min: true,
                    max: true
                }, addMinMax);
                if (ticks.length > 0) {
                    if (!addMinMax.min && ticks[0].valueOf() === min.valueOf())
                        ticks.shift();
                    if (!addMinMax.max || ticks[ticks.length - 1].valueOf() !== max.valueOf())
                        ticks.pop()
                }
            },
            _initializeMinorTicksOptions: function(dataType, min, max, screenDelta, ticksInfo, options) {
                var self = this,
                    businessDelta,
                    hasMinorsCount = utils.isDefined(options.minorTickCount);
                $.extend(true, options, {
                    addMinMax: {
                        min: false,
                        max: false
                    },
                    deltaCoef: self._getDeltaCoef(screenDelta, min, max)
                }, options);
                options.numberMultipliers = hasMinorsCount ? [options.minorTickCount + 1] : options.numberMultipliers;
                options.gridSpacingFactor = hasMinorsCount ? 0 : options.gridSpacingFactor;
                if (!hasMinorsCount && ticksInfo.majorTicks.length > 1) {
                    businessDelta = Math.abs(ticksInfo.majorTicks[0] - ticksInfo.majorTicks[1]);
                    if (self.needTickIntervalCalculation(businessDelta, ticksInfo.minorTickInterval, options.incidentOccured)) {
                        ticksInfo.minorTickInterval = core.minorTickIntervalCalculator.getTickInterval(dataType, businessDelta, businessDelta * options.deltaCoef, options.gridSpacingFactor, options.numberMultipliers);
                        if (utils.isNumber(min))
                            options.tickInterval = ticksInfo.minorTickInterval;
                        else
                            options.tickInterval = undefined
                    }
                }
            },
            _getDataType: function(value) {
                return utils.isDate(value) ? 'datetime' : 'numeric'
            },
            _getDeltaCoef: function(screenDelta, max, min) {
                return screenDelta / Math.abs(max - min)
            },
            _initializeMajorTicksOptions: function(dataType, min, max, screenDelta, ticksInfo, options) {
                var businessDelta;
                options.type = dataType;
                options.screenDelta = screenDelta;
                $.extend(true, options, {
                    min: min,
                    max: max,
                    screenDelta: screenDelta,
                    isHorizontal: true
                });
                if (utils.isDefined(min) && utils.isDefined(max)) {
                    businessDelta = Math.abs(max - min);
                    options.businessDelta = businessDelta;
                    if (this.needTickIntervalCalculation(businessDelta, ticksInfo.majorTickInterval, options.incidentOccured)) {
                        options.isStartTickGenerated = true;
                        ticksInfo.majorTickInterval = core.tickIntervalCalculator.getTickInterval(options);
                        options.tickInterval = ticksInfo.majorTickInterval
                    }
                }
            },
            _getTextFunc: function(options) {
                return options.getText || function(value) {
                        return value.toString()
                    }
            },
            _generateTicks: function(options) {
                var self = this,
                    ticks = [],
                    tick,
                    boundedRule = options.max - options.min > 0,
                    leftBound,
                    rightBound,
                    tickInterval,
                    isStartTickGenerated = options.isStartTickGenerated,
                    businessDelta,
                    useTicksAutoArrangement = options.useTicksAutoArrangement;
                options.type = utils.isDefined(options.type) && options.type !== 'continuous' ? options.type : self._getDataType(options.min);
                options.businessDelta = Math.abs(options.max - options.min);
                if (!utils.isDefined(options.min) || !utils.isDefined(options.max) || isNaN(options.min) || isNaN(options.max)) {
                    ticks = options.isHorizontal ? ['canvas_position_left', 'canvas_position_center', 'canvas_position_right'] : ['canvas_position_bottom', 'canvas_position_middle', 'canvas_position_top'];
                    useTicksAutoArrangement = false;
                    ticks.hideLabels = true
                }
                else {
                    tickInterval = $.isNumeric(options.min) && $.isNumeric(options.max) && !$.isNumeric(options.tickInterval) ? undefined : options.tickInterval;
                    businessDelta = options.type === 'logarithmic' ? Math.abs(utils.getLog(options.min, options.base) - utils.getLog(options.max, options.base)) : options.businessDelta;
                    if (this.needTickIntervalCalculation(businessDelta, tickInterval, options.incidentOccured)) {
                        isStartTickGenerated = utils.isDefined(isStartTickGenerated) ? isStartTickGenerated : true;
                        tickInterval = core.tickIntervalCalculator.getTickInterval(options)
                    }
                    ticks.tickInterval = tickInterval;
                    self.isTestStartTickGenerated = isStartTickGenerated;
                    self.isTestTickInterval = tickInterval;
                    self.testGridSpacingFactor = options.gridSpacingFactor;
                    if (tickInterval && tickInterval.valueOf() !== 0 && options.min.valueOf() !== options.max.valueOf()) {
                        tick = isStartTickGenerated ? self._generateStartTick(tickInterval, options) : options.min;
                        do {
                            ticks.push(tick);
                            tick = self._nextTick(tick, tickInterval, options);
                            if (ticks[ticks.length - 1].valueOf() === tick.valueOf())
                                break;
                            leftBound = tick - options.min > 0;
                            rightBound = options.max - tick > 0
                        } while (boundedRule === leftBound && boundedRule === rightBound);
                        ticks.push(tick);
                        self._correctBoundedTicks(options.min, options.max, ticks, options.addMinMax)
                    }
                }
                return ticks
            },
            _getAutoArrangementStep: function(ticks, options) {
                var self = this,
                    requiredValuesCount,
                    addedSpacing = options.isHorizontal ? options.textSpacing : 0;
                if (options.getCustomAutoArrangementStep)
                    return options.getCustomAutoArrangementStep(ticks, options);
                if (options.maxDisplayValueSize > 0) {
                    requiredValuesCount = Math.floor((options.screenDelta + options.textSpacing) / (options.maxDisplayValueSize + addedSpacing));
                    return Math.ceil((options.ticksCount || ticks.length) / requiredValuesCount)
                }
                return 1
            },
            _getAutoArrangementTicks: function(ticks, options, step) {
                var self = this,
                    resultTicks = ticks,
                    i;
                if (step > 1) {
                    resultTicks = [];
                    for (i = 0; i < ticks.length; i += step)
                        resultTicks.push(ticks[i])
                }
                return resultTicks
            },
            isOverlappedTicks: function(ticks, options) {
                var self = this;
                options.maxDisplayValueSize = self._getValueSize(ticks, options);
                return self._getAutoArrangementStep(ticks, options) > 1
            },
            needTickIntervalCalculation: function(businessDelta, tickInterval, incidentOccured) {
                var date;
                if (utils.isDefined(tickInterval)) {
                    if (!utils.isNumber(tickInterval)) {
                        date = new Date;
                        tickInterval = utils.addInterval(date, tickInterval) - date;
                        if (!tickInterval)
                            return true
                    }
                    if (utils.isNumber(tickInterval))
                        if (tickInterval > 0 && businessDelta / tickInterval > TICKS_COUNT_LIMIT) {
                            if (incidentOccured)
                                incidentOccured('Tick count is too big. So, the tick interval is specified automatically.')
                        }
                        else
                            return false
                }
                return true
            },
            getTickIntervals: function(min, max, screenDelta, majorTicksOptions, minorTicksOptions) {
                var self = this,
                    i,
                    businessDelta,
                    dataType = self._getDataType(min),
                    ticksInfo = {
                        majorTickInterval: majorTicksOptions.tickInterval,
                        minorTickInterval: minorTicksOptions.tickInterval,
                        majorTicks: []
                    };
                self._initializeMajorTicksOptions(dataType, min, max, screenDelta, ticksInfo, majorTicksOptions);
                if (utils.isDefined(min) && utils.isDefined(max)) {
                    ticksInfo.majorTicks.push(min);
                    ticksInfo.majorTicks.push(self._nextTick(min, ticksInfo.majorTickInterval, {
                        min: min,
                        max: max,
                        setTicksAtUnitBeginning: majorTicksOptions.setTicksAtUnitBeginning
                    }));
                    businessDelta = Math.abs(ticksInfo.majorTicks[0] - ticksInfo.majorTicks[1]);
                    self._initializeMinorTicksOptions(dataType, min, max, screenDelta, ticksInfo, minorTicksOptions)
                }
                return ticksInfo
            },
            getFullTicks: function(min, max, screenDelta, majorTicksOptions, minorTicksOptions) {
                var self = this,
                    i,
                    dataType = self._getDataType(min),
                    ticksInfo = {
                        customBoundaryTicks: [],
                        fullTicks: [],
                        majorTickInterval: majorTicksOptions.tickInterval,
                        majorTicks: [],
                        minorTickInterval: minorTicksOptions.tickInterval,
                        minorTicks: []
                    };
                self._initializeMajorTicksOptions(dataType, min, max, screenDelta, ticksInfo, majorTicksOptions);
                ticksInfo.majorTicks = self.getTicks(majorTicksOptions);
                if (utils.isDefined(min) && utils.isDefined(max) && ticksInfo.majorTicks.length > 0) {
                    if (ticksInfo.majorTicks.autoArrangementStep && ticksInfo.majorTicks.autoArrangementStep > 1 && !utils.isDefined(minorTicksOptions.tickInterval) && !utils.isDefined(minorTicksOptions.minorTickCount))
                        minorTicksOptions.tickInterval = ticksInfo.minorTickInterval = majorTicksOptions.tickInterval;
                    self._initializeMinorTicksOptions(dataType, min, max, screenDelta, ticksInfo, minorTicksOptions);
                    self._addLeftBoudedTicks(ticksInfo, min, minorTicksOptions);
                    for (i = 0; i < ticksInfo.majorTicks.length - 1; i++) {
                        ticksInfo.fullTicks.push(ticksInfo.majorTicks[i]);
                        self._addMinorTicks(ticksInfo.majorTicks[i], ticksInfo.majorTicks[i + 1], ticksInfo, minorTicksOptions)
                    }
                    self._addRightBoudedTicks(ticksInfo, max, minorTicksOptions)
                }
                return ticksInfo
            },
            getTicks: function(options) {
                var self = this,
                    step,
                    maxDisplayValue,
                    ticks = options.customTicks ? options.customTicks : self._generateTicks(options);
                if (options.useTicksAutoArrangement) {
                    options.maxDisplayValueSize = self._getValueSize(ticks, options);
                    step = self._getAutoArrangementStep(ticks, options);
                    if (step > 1) {
                        if (utils.isDefined(options.tickInterval) || utils.isDefined(options.customTicks))
                            ticks = self._getAutoArrangementTicks(ticks, options, step);
                        else
                            ticks = self._generateTicks($.extend({}, options, {gridSpacingFactor: options.maxDisplayValueSize}));
                        ticks.autoArrangementStep = step
                    }
                    self._removeInvalidDatesWithUnitBegining(ticks, options)
                }
                return ticks
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file numericTranslatorX.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            utils = DX.utils,
            math = Math;
        DX.viz.core.NumericTranslatorX = {
            zoomX: function(min, max) {
                var self = this,
                    businessRange = self.businessRange;
                businessRange.minVisibleX = min;
                businessRange.maxVisibleX = max;
                businessRange.applyEqualLimitsMargins();
                self.init()
            },
            translateX: function(bpX) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas,
                    result;
                var specialValue = self.translateSpecialCases(self, bpX, "X");
                if (utils.isDefined(specialValue))
                    return specialValue;
                if (bpX < ranges.minX)
                    return null;
                if (bpX > ranges.maxX)
                    return null;
                if (ranges.invertX)
                    result = canvas.left + (1 - (bpX - ranges.minVisibleX) / (ranges.maxVisibleX - ranges.minVisibleX)) * self.width;
                else
                    result = canvas.left + (bpX - ranges.minVisibleX) / (ranges.maxVisibleX - ranges.minVisibleX) * self.width;
                return math.round(result)
            },
            untranslateX: function(posX) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas;
                if (posX < canvas.left)
                    return null;
                if (posX > canvas.left + self.width)
                    return null;
                if (ranges.invertX)
                    return ranges.minVisibleX + (self.width - (posX - canvas.left)) * (ranges.maxVisibleX - ranges.minVisibleX) / self.width;
                else
                    return ranges.minVisibleX + (posX - canvas.left) * (ranges.maxVisibleX - ranges.minVisibleX) / self.width
            },
            getIntervalX: function() {
                var self = this,
                    result = 0;
                if (self.businessRange.intervalX !== undefined)
                    result = self.width * self.businessRange.intervalX / (self.businessRange.maxVisibleX - self.businessRange.minVisibleX);
                return Math.round(result)
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file numericTranslatorY.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            utils = DX.utils,
            math = Math;
        DX.viz.core.NumericTranslatorY = {
            zoomY: function(min, max) {
                var self = this,
                    businessRange = self.businessRange;
                businessRange.minVisibleY = min;
                businessRange.maxVisibleY = max;
                businessRange.applyEqualLimitsMargins();
                self.init()
            },
            translateY: function(bpY) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas,
                    result;
                var specialValue = self.translateSpecialCases(self, bpY, "Y");
                if (utils.isDefined(specialValue))
                    return specialValue;
                if (bpY < ranges.minY)
                    return null;
                if (bpY > ranges.maxY)
                    return null;
                if (ranges.invertY)
                    result = canvas.height - canvas.bottom - (1 - (bpY - ranges.minVisibleY) / (ranges.maxVisibleY - ranges.minVisibleY)) * self.height;
                else
                    result = canvas.height - canvas.bottom - (bpY - ranges.minVisibleY) / (ranges.maxVisibleY - ranges.minVisibleY) * self.height;
                return math.round(result)
            },
            untranslateY: function(posY) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas;
                if (posY < canvas.top)
                    return null;
                if (posY > canvas.top + self.height)
                    return null;
                if (ranges.invertY)
                    return ranges.maxVisibleY - (self.height - (posY - canvas.top)) * (ranges.maxVisibleY - ranges.minVisibleY) / self.height;
                else
                    return ranges.maxVisibleY - (posY - canvas.top) * (ranges.maxVisibleY - ranges.minVisibleY) / self.height
            },
            getIntervalY: function() {
                var self = this,
                    result = 0;
                if (self.businessRange.intervalY !== undefined)
                    result = self.height * self.businessRange.intervalY / (self.businessRange.maxVisibleY - self.businessRange.minVisibleY);
                return Math.round(result)
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file datetimeTranslatorX.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            utils = DX.utils,
            math = Math;
        DX.viz.core.DatetimeTranslatorX = {
            zoomX: function(min, max) {
                var self = this,
                    businessRange = self.businessRange;
                businessRange.minVisibleX = min;
                businessRange.maxVisibleX = max;
                businessRange.applyEqualLimitsMargins();
                self.init()
            },
            translateX: function(bpX) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas,
                    result;
                var specialValue = self.translateSpecialCases(self, bpX, "X");
                if (utils.isDefined(specialValue))
                    return specialValue;
                if (bpX < ranges.minX)
                    return null;
                if (bpX > ranges.maxX)
                    return null;
                if (ranges.invertX)
                    result = canvas.left + (1 - (bpX - ranges.minVisibleX) / (ranges.maxVisibleX - ranges.minVisibleX)) * self.width;
                else
                    result = canvas.left + (bpX - ranges.minVisibleX) / (ranges.maxVisibleX - ranges.minVisibleX) * self.width;
                return math.round(result)
            },
            untranslateX: function(posX) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas;
                if (posX < canvas.left)
                    return null;
                if (posX > canvas.left + self.width)
                    return null;
                if (ranges.invertX)
                    return new Date(ranges.minVisibleX.valueOf() + (self.width - (posX - canvas.left)) * (ranges.maxVisibleX - ranges.minVisibleX) / self.width);
                else
                    return new Date(ranges.minVisibleX.valueOf() + (posX - canvas.left) * (ranges.maxVisibleX - ranges.minVisibleX) / self.width)
            },
            getIntervalX: function() {
                var self = this,
                    result = 0;
                if (self.businessRange.intervalX !== undefined)
                    result = self.width * self.businessRange.intervalX / (self.businessRange.maxVisibleX - self.businessRange.minVisibleX);
                return Math.round(result)
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file datetimeTranslatorY.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            utils = DX.utils,
            math = Math;
        DX.viz.core.DatetimeTranslatorY = {
            zoomY: function(min, max) {
                var self = this,
                    businessRange = self.businessRange;
                businessRange.minVisibleY = min;
                businessRange.maxVisibleY = max;
                businessRange.applyEqualLimitsMargins();
                self.init()
            },
            translateY: function(bpY) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas,
                    result;
                var specialValue = self.translateSpecialCases(self, bpY, "Y");
                if (utils.isDefined(specialValue))
                    return specialValue;
                if (bpY < ranges.minY)
                    return null;
                if (bpY > ranges.maxY)
                    return null;
                if (ranges.invertY)
                    result = canvas.height - canvas.bottom - (1 - (bpY - ranges.minVisibleY) / (ranges.maxVisibleY - ranges.minVisibleY)) * self.height;
                else
                    result = canvas.height - canvas.bottom - (bpY - ranges.minVisibleY) / (ranges.maxVisibleY - ranges.minVisibleY) * self.height;
                return math.round(result)
            },
            untranslateY: function(posY) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas;
                if (posY < canvas.top)
                    return null;
                if (posY > canvas.top + self.height)
                    return null;
                if (ranges.invertY)
                    return new Date(ranges.maxVisibleY.valueOf() - (self.height - (posY - canvas.top)) * (ranges.maxVisibleY - ranges.minVisibleY) / self.height);
                else
                    return new Date(ranges.maxVisibleY.valueOf() - (posY - canvas.top) * (ranges.maxVisibleY - ranges.minVisibleY) / self.height)
            },
            getIntervalY: function() {
                var self = this,
                    result = 0;
                if (self.businessRange.intervalY !== undefined)
                    result = self.height * self.businessRange.intervalY / (self.businessRange.maxVisibleY - self.businessRange.minVisibleY);
                return Math.round(result)
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file categoryTranslatorX.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            utils = DX.utils,
            math = Math;
        DX.viz.core.CategoryTranslatorX = {
            translateX: function(category) {
                var self = this,
                    canvas = self.canvas,
                    categoryRecord,
                    stickX = self.businessRange.stickX,
                    result = 0;
                var specialValue = self.translateSpecialCases(self, category, "X");
                if (utils.isDefined(specialValue))
                    return specialValue;
                categoryRecord = self.categoriesXToPoints[category];
                if (!categoryRecord)
                    return 0;
                if (stickX)
                    result = canvas.left + self.horizontalInterval * categoryRecord.index;
                else
                    result = canvas.left + self.horizontalInterval * (categoryRecord.index + 0.5);
                return math.round(result)
            },
            untranslateX: function(posX) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas,
                    result = 0,
                    delta;
                if (posX < canvas.left)
                    return null;
                if (posX > canvas.left + self.width)
                    return null;
                if (ranges.stickX)
                    if (posX < canvas.left + self.horizontalInterval / 2)
                        result = 0;
                    else if (posX > canvas.left + canvas.width - self.horizontalInterval / 2)
                        result = self.categoriesXNumber - 1;
                    else
                        result = math.ceil((posX - canvas.left) / self.horizontalInterval);
                else if (posX === canvas.width - canvas.right)
                    result = math.floor((posX - canvas.left) / self.horizontalInterval) - 1;
                else
                    result = math.floor((posX - canvas.left) / self.horizontalInterval);
                if (ranges.invertX)
                    result = self.categoriesXNumber - result - 1;
                return self.categories[result]
            },
            zoomX: function(min, max) {
                var self = this,
                    businessRange = self.businessRange;
                businessRange.minVisibleX = min;
                businessRange.maxVisibleX = max;
                businessRange.applyEqualLimitsMargins();
                self.init()
            },
            getIntervalX: function() {
                var self = this;
                return self.horizontalInterval
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file categoryTranslatorY.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            utils = DX.utils,
            math = Math;
        DX.viz.core.CategoryTranslatorY = {
            translateY: function(category) {
                var self = this,
                    canvas = self.canvas,
                    categoryRecord,
                    stickY = self.businessRange.stickY,
                    result = 0;
                var specialValue = self.translateSpecialCases(self, category, "Y");
                if (utils.isDefined(specialValue))
                    return specialValue;
                categoryRecord = self.categoriesYToPoints[category];
                if (!categoryRecord)
                    return 0;
                if (stickY)
                    result = canvas.top + self.verticalInterval * categoryRecord.index;
                else
                    result = canvas.top + self.verticalInterval * (categoryRecord.index + 0.5);
                return math.round(result)
            },
            untranslateY: function(posY) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas,
                    result = 0;
                if (posY < canvas.top)
                    return null;
                if (posY > canvas.top + self.height)
                    return null;
                if (ranges.stickY)
                    if (posY < canvas.top + self.verticalInterval / 2)
                        result = 0;
                    else if (posY > canvas.top + canvas.height - self.verticalInterval / 2)
                        result = self.categoriesYNumber - 1;
                    else
                        result = math.ceil((posY - canvas.top) / self.verticalInterval);
                else
                    result = math.ceil((posY - canvas.top) / self.verticalInterval);
                if (ranges.invertY)
                    if (ranges.stickY)
                        result = self.categoriesYNumber - result - 1;
                    else
                        result = self.categoriesYNumber - result;
                return self.categories[result]
            },
            zoomY: function(min, max) {
                var self = this,
                    businessRange = self.businessRange;
                businessRange.minVisibleY = min;
                businessRange.maxVisibleY = max;
                businessRange.applyEqualLimitsMargins();
                self.init()
            },
            getIntervalY: function() {
                var self = this;
                return self.verticalInterval
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file logarithmicTranslatorX.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            utils = DX.utils,
            math = Math;
        DX.viz.core.LogarifmicTranslatorX = {
            translateX: function(bpX) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas,
                    result,
                    power,
                    coef,
                    delta,
                    basePower,
                    coord,
                    startPos;
                var specialValue = self.translateSpecialCases(self, bpX, "X");
                if (utils.isDefined(specialValue))
                    return specialValue;
                if (bpX < ranges.minX)
                    return null;
                if (bpX > ranges.maxX)
                    return null;
                if (utils.isExponential(bpX)) {
                    startPos = bpX.toString().indexOf('e') + 1;
                    basePower = parseInt(bpX.toString().substring(startPos))
                }
                else
                    basePower = math.floor(utils.getLog(bpX, ranges.baseX));
                coef = self.width / (utils.getLog(ranges.maxVisibleX, ranges.baseX) - utils.getLog(ranges.minVisibleX, ranges.baseX));
                delta = basePower - utils.getLog(ranges.minVisibleX, ranges.baseX);
                result = canvas.left + coef * delta + (bpX - utils.raiseTo(basePower, ranges.baseX)) / (utils.raiseTo(basePower + 1, ranges.baseX) - utils.raiseTo(basePower, ranges.baseX)) * coef;
                if (ranges.invertX)
                    return canvas.width - canvas.right - (math.round(result) - canvas.left);
                else
                    return math.round(result)
            },
            untranslateX: function(posX) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas,
                    coef,
                    a,
                    delta,
                    coord;
                if (posX < canvas.left)
                    return null;
                if (posX > canvas.left + self.width)
                    return null;
                if (ranges.invertX)
                    coord = canvas.width - canvas.right - posX;
                else
                    coord = posX - canvas.left;
                coef = self.width / (utils.getLog(ranges.maxVisibleX, ranges.baseX) - utils.getLog(ranges.minVisibleX, ranges.baseX));
                a = utils.raiseTo(utils.getLog(ranges.minVisibleX, ranges.baseX) + math.round(coord / coef - 0.01), ranges.baseX);
                delta = utils.raiseTo(utils.getLog(ranges.minVisibleX, ranges.baseX) + math.ceil(coord / coef - 0.01), ranges.baseX) - a;
                return a + (coord - math.round((utils.getLog(a, ranges.baseX) - utils.getLog(ranges.minVisibleX, ranges.baseX)) * coef)) * delta / coef
            },
            getIntervalX: function() {
                var self = this,
                    ranges = self.businessRange,
                    result = 0;
                result = self.width / utils.getLog(ranges.maxVisibleX / ranges.minVisibleX, ranges.baseX) * ((utils.raiseTo(ranges.intervalX, ranges.baseX) - 1) / (ranges.baseX - 1));
                return math.round(result)
            },
            zoomX: function(min, max) {
                var self = this,
                    ranges = self.businessRange,
                    businessRange = self.businessRange,
                    newMinX,
                    newMaxX,
                    coef,
                    delta,
                    basePower,
                    startPos;
                if (utils.isExponential(min)) {
                    startPos = min.toString().indexOf('e') + 1;
                    basePower = parseInt(min.toString().substring(startPos))
                }
                else
                    basePower = math.floor(utils.getLog(min, ranges.baseX));
                newMinX = utils.raiseTo(basePower, ranges.baseX);
                if (utils.isExponential(max)) {
                    startPos = max.toString().indexOf('e') + 1;
                    basePower = parseInt(max.toString().substring(startPos))
                }
                else
                    basePower = math.ceil(utils.getLog(max, ranges.baseX));
                newMaxX = utils.raiseTo(basePower, ranges.baseX);
                businessRange.minVisibleX = newMinX;
                businessRange.maxVisibleX = newMaxX;
                businessRange.applyEqualLimitsMargins();
                self.init()
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file logarithmicTranslatorY.js */
    (function($, DX, undefined) {
        var Class = DX.Class,
            utils = DX.utils,
            math = Math;
        DX.viz.core.LogarifmicTranslatorY = {
            translateY: function(bpY) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas,
                    result,
                    basePower,
                    coef,
                    delta,
                    startPos;
                var specialValue = self.translateSpecialCases(self, bpY, "Y");
                if (utils.isDefined(specialValue))
                    return specialValue;
                if (bpY < ranges.minY)
                    return null;
                if (bpY > ranges.maxY)
                    return null;
                if (utils.isExponential(bpY)) {
                    startPos = bpY.toString().indexOf('e') + 1;
                    basePower = parseInt(bpY.toString().substring(startPos))
                }
                else
                    basePower = math.floor(utils.getLog(bpY, ranges.baseY));
                coef = self.height / (utils.getLog(ranges.maxVisibleY, ranges.baseY) - utils.getLog(ranges.minVisibleY, ranges.baseY));
                delta = basePower - utils.getLog(ranges.minVisibleY, ranges.baseY);
                result = canvas.height - canvas.bottom - coef * delta - (bpY - utils.raiseTo(basePower, ranges.baseY)) / (utils.raiseTo(basePower + 1, ranges.baseY) - utils.raiseTo(basePower, ranges.baseY)) * coef;
                if (ranges.invertY)
                    return canvas.height + canvas.top - math.round(result) - canvas.bottom;
                else
                    return math.round(result)
            },
            untranslateY: function(posY) {
                var self = this,
                    ranges = self.businessRange,
                    canvas = self.canvas,
                    coef,
                    a,
                    delta,
                    coord;
                if (posY < canvas.top)
                    return null;
                if (posY > canvas.top + self.height)
                    return null;
                if (ranges.invertY)
                    coord = posY - canvas.top;
                else
                    coord = canvas.height - posY - canvas.bottom;
                coef = self.height / (utils.getLog(ranges.maxVisibleY, ranges.baseY) - utils.getLog(ranges.minVisibleY, ranges.baseY));
                a = utils.raiseTo(utils.getLog(ranges.minVisibleY, ranges.baseY) + math.round(coord / coef - 0.1), ranges.baseY);
                delta = utils.raiseTo(utils.getLog(ranges.minVisibleY, ranges.baseY) + math.ceil(coord / coef - 0.1), ranges.baseY) - a;
                return a + (coord - math.round((utils.getLog(a, ranges.baseY) - utils.getLog(ranges.minVisibleY, ranges.baseY)) * coef)) * delta / coef
            },
            getIntervalY: function(self) {
                var self = this,
                    ranges = self.businessRange,
                    result = 0;
                result = self.height / (utils.getLog(self.businessRange.maxVisibleY, ranges.baseY) - utils.getLog(self.businessRange.minVisibleY, ranges.baseY));
                return math.round(result)
            },
            zoomY: function(min, max) {
                var self = this,
                    ranges = self.businessRange,
                    businessRange = self.businessRange,
                    newMinY,
                    newMaxY,
                    coef,
                    delta,
                    basePower,
                    startPos;
                if (utils.isExponential(min)) {
                    startPos = min.toString().indexOf('e') + 1;
                    basePower = parseInt(min.toString().substring(startPos))
                }
                else
                    basePower = math.floor(utils.getLog(min, ranges.baseY));
                newMinY = utils.raiseTo(basePower, ranges.baseY);
                if (utils.isExponential(max)) {
                    startPos = max.toString().indexOf('e') + 1;
                    basePower = parseInt(max.toString().substring(startPos))
                }
                else
                    basePower = math.ceil(utils.getLog(max, ranges.baseY));
                newMaxY = utils.raiseTo(basePower, ranges.baseY);
                businessRange.minVisibleY = newMinY;
                businessRange.maxVisibleY = newMaxY;
                businessRange.applyEqualLimitsMargins();
                self.init()
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file translator1D.js */
    (function(DX, undefined) {
        var NaN = window.NaN,
            Number = window.Number;
        DX.viz.core.Translator1D = DX.Class.inherit({
            ctor: function(domainStart, domainEnd, codomainStart, codomainEnd) {
                DX.utils.debug.assertParam(domainStart, 'domainStart was not passed');
                DX.utils.debug.assertParam(domainEnd, 'domainEnd was not passed');
                DX.utils.debug.assertParam(codomainStart, 'codomainStart was not passed');
                DX.utils.debug.assertParam(codomainEnd, 'codomainEnd was not passed');
                this.setup({
                    domainStart: domainStart,
                    domainEnd: domainEnd,
                    codomainStart: codomainStart,
                    codomainEnd: codomainEnd
                })
            },
            setup: function(settings) {
                var self = this;
                settings = settings || {};
                self._domainStart = Number(settings.domainStart);
                self._domainEnd = Number(settings.domainEnd);
                self._codomainStart = Number(settings.codomainStart);
                self._codomainEnd = Number(settings.codomainEnd);
                self._domainDelta = self._domainEnd - self._domainStart;
                self._codomainDelta = self._codomainEnd - self._codomainStart;
                return self
            },
            getDomainStart: function() {
                return this._domainStart
            },
            getDomainEnd: function() {
                return this._domainEnd
            },
            getCodomainStart: function() {
                return this._codomainStart
            },
            getCodomainEnd: function() {
                return this._codomainEnd
            },
            getDomainRange: function() {
                return this._domainDelta
            },
            getCodomainRange: function() {
                return this._codomainDelta
            },
            translate: function(value) {
                var self = this,
                    ratio = (value - self._domainStart) / self._domainDelta;
                return 0 <= ratio && ratio <= 1 ? self._codomainStart + ratio * self._codomainDelta : NaN
            },
            adjust: function(value) {
                var self = this,
                    ratio = (value - self._domainStart) / self._domainDelta,
                    result = NaN;
                if (ratio < 0)
                    result = self._domainStart;
                else if (ratio > 1)
                    result = self._domainEnd;
                else if (0 <= ratio && ratio <= 1)
                    result = Number(value);
                return result
            }
        })
    })(DevExpress);
    /*! Module viz-core, file translator2D.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            core = DX.viz.core,
            CANVAS_PROP = ['width', 'height', 'left', 'top', 'bottom', 'right'];
        core.Translator2D = DX.Class.inherit(function() {
            var ctor = function(businessRanges, canvas) {
                    this.canvas = validateCanvas(canvas);
                    this.updateBusinessRange(businessRanges)
                };
            var validateCanvas = function(canvas) {
                    $.each(CANVAS_PROP, function(_, prop) {
                        var val = canvas[prop];
                        canvas[prop] = parseInt(val) || 0
                    });
                    return canvas
                };
            var dispose = function() {
                    var _this = this;
                    _this.canvas = null;
                    _this.businessRange.dispose();
                    _this.businessRange = null;
                    _this.categoriesXToPoints = null;
                    _this.categoriesYToPoints = null;
                    _this.categories = null
                };
            var init = function() {
                    var self = this,
                        canvas = self.canvas,
                        range = self.businessRange,
                        i,
                        category;
                    self.width = canvas.width - canvas.left - canvas.right;
                    self.height = canvas.height - canvas.top - canvas.bottom;
                    self.set('X');
                    self.set('Y')
                };
            var set = function(type) {
                    var self = this,
                        range = self.businessRange,
                        categories = self.businessRange['categories' + type],
                        script,
                        size,
                        position;
                    if (type === 'X') {
                        size = 'width';
                        position = 'horizontal'
                    }
                    else {
                        size = 'height';
                        position = 'vertical'
                    }
                    switch (range['axisType' + type]) {
                        case'logarithmic':
                            script = core['LogarifmicTranslator' + type];
                            break;
                        case'numeric':
                            script = core['NumericTranslator' + type];
                            break;
                        case'categories':
                            script = core['CategoryTranslator' + type];
                            self['categories' + type + 'Number'] = categories.length;
                            self.categories = categories;
                            if (range['stick' + type])
                                self[position + 'Interval'] = self[size] / (self['categories' + type + 'Number'] - 1);
                            else
                                self[position + 'Interval'] = self[size] / self['categories' + type + 'Number'];
                            self['categories' + type + 'ToPoints'] = makeCategoriesToPoints(categories, self.businessRange['invert' + type]);
                            break;
                        case'datetime':
                            script = core['DatetimeTranslator' + type];
                            break;
                        default:
                            if (categories) {
                                script = core['CategoryTranslator' + type];
                                self['categories' + type + 'Number'] = categories.length;
                                if (range['stick' + type])
                                    self[position + 'Interval'] = self[size] / (self['categories' + type + 'Number'] - 1);
                                else
                                    self[position + 'Interval'] = self[size] / self['categories' + type + 'Number'];
                                self['categories' + type + 'ToPoints'] = makeCategoriesToPoints(categories, self.businessRange['invert' + type]);
                                range['axisType' + type] = 'categories'
                            }
                            else if (utils.isNumber(range['min' + type])) {
                                script = core['NumericTranslator' + type];
                                range['axisType' + type] = 'numeric'
                            }
                            else if (utils.isDate(range['min' + type])) {
                                script = core['DatetimeTranslator' + type];
                                range['axisType' + type] = 'datetime'
                            }
                            break
                    }
                    if (script === undefined)
                        script = core['NumericTranslator' + type];
                    self['zoom' + type] = script['zoom' + type];
                    self['translate' + type] = script['translate' + type];
                    self['getInterval' + type] = script['getInterval' + type];
                    self['untranslate' + type] = script['untranslate' + type]
                };
            var updateBusinessRange = function(businessRange) {
                    this.businessRange = businessRange;
                    if (businessRange.minVisibleX === undefined)
                        businessRange.minVisibleX = businessRange.minX;
                    if (businessRange.maxVisibleX === undefined)
                        businessRange.maxVisibleX = businessRange.maxX;
                    if (businessRange.minVisibleY === undefined)
                        businessRange.minVisibleY = businessRange.minY;
                    if (businessRange.maxVisibleY === undefined)
                        businessRange.maxVisibleY = businessRange.maxY;
                    this.init()
                };
            var getBusinessRange = function() {
                    return this.businessRange
                };
            var getBusinessVisibleArea = function() {
                    var range = this.businessRange,
                        visibleArea = {};
                    visibleArea.minX = range.minVisibleX;
                    visibleArea.maxX = range.maxVisibleX;
                    visibleArea.minY = range.minVisibleY;
                    visibleArea.maxY = range.maxVisibleY;
                    visibleArea.axisTypeX = range.axisTypeX;
                    visibleArea.axisTypeY = range.axisTypeY;
                    if (visibleArea.axisTypeX === 'logarithmic')
                        visibleArea.baseX = range.baseX;
                    if (visibleArea.axisTypeY === 'logarithmic')
                        visibleArea.baseY = range.baseY;
                    if (range.categoriesX) {
                        visibleArea.categoriesX = range.categoriesX;
                        visibleArea.minCategoryXPos = 0;
                        visibleArea.maxCategoryXPos = visibleArea.minCategoryXPos + visibleArea.categoriesX.length - 1
                    }
                    if (range.categoriesY) {
                        visibleArea.categoriesY = range.categoriesY;
                        visibleArea.minCategoryYPos = 0;
                        visibleArea.maxCategoryYPos = visibleArea.minCategoryYPos + visibleArea.categoriesY.length - 1
                    }
                    return visibleArea
                };
            var getCanvasVisibleArea = function() {
                    var canvas = this.canvas;
                    return {
                            minX: canvas.left,
                            maxX: canvas.width - canvas.right,
                            minY: canvas.top,
                            maxY: canvas.height - canvas.bottom
                        }
                };
            var makeCategoriesToPoints = function(categories, invert) {
                    var categoriesToPoints = {},
                        category,
                        i;
                    if (invert)
                        for (i = categories.length - 1; i >= 0; i--) {
                            category = categories[categories.length - 1 - i];
                            categoriesToPoints[category] = {
                                name: category,
                                index: i
                            }
                        }
                    else
                        for (i = 0; i < categories.length; i++) {
                            category = categories[i];
                            categoriesToPoints[category] = {
                                name: category,
                                index: i
                            }
                        }
                    return categoriesToPoints
                };
            var translateSpecialCases = function(self, value, position) {
                    var parsedValue = (value + '').match(/canvas_position_(.*)/),
                        canvas = self.canvas,
                        categoryRecord,
                        range = self.businessRange;
                    if (parsedValue) {
                        value = parsedValue[1];
                        if (value === 'default') {
                            if (range['minVisible' + position] <= 0 && 0 <= range['maxVisible' + position])
                                return self['translate' + position](0);
                            if (position === 'X')
                                if (range.invertX)
                                    return canvas.left + self.width;
                                else
                                    return canvas.left;
                            else if (range.invertY)
                                return canvas.top;
                            else
                                return canvas.top + self.height
                        }
                        if (position === "X") {
                            if (value === 'left')
                                return canvas.left;
                            if (value === 'center')
                                return canvas.left + self.width / 2;
                            if (value === 'right')
                                return canvas.left + self.width
                        }
                        else {
                            if (value === 'bottom')
                                return canvas.top + self.height;
                            if (value === 'middle')
                                return canvas.top + self.height / 2;
                            if (value === 'top')
                                return canvas.top
                        }
                    }
                    return null
                };
            var prototypeObject = {
                    ctor: ctor,
                    dispose: dispose,
                    init: init,
                    makeCategoriesToPoints: makeCategoriesToPoints,
                    translateSpecialCases: translateSpecialCases,
                    getCanvasVisibleArea: getCanvasVisibleArea,
                    getBusinessVisibleArea: getBusinessVisibleArea,
                    updateBusinessRange: updateBusinessRange,
                    getBusinessRange: getBusinessRange
                };
            prototypeObject.set = set;
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz-core, file rectangle.js */
    (function(DX, undefined) {
        var isFinite = window.isFinite;
        DX.viz.core.Rectangle = DX.Class.inherit({
            ctor: function(options) {
                var self = this;
                options = options || {};
                self.left = Number(options.left) || 0;
                self.right = Number(options.right) || 0;
                self.top = Number(options.top) || 0;
                self.bottom = Number(options.bottom) || 0
            },
            width: function() {
                return this.right - this.left
            },
            height: function() {
                return this.bottom - this.top
            },
            horizontalMiddle: function() {
                return (this.left + this.right) / 2
            },
            verticalMiddle: function() {
                return (this.top + this.bottom) / 2
            },
            raw: function() {
                var self = this;
                return {
                        left: self.left,
                        top: self.top,
                        right: self.right,
                        bottom: self.bottom
                    }
            },
            clone: function() {
                return new this.constructor(this.raw())
            },
            move: function(dx, dy) {
                var result = this.clone();
                if (isFinite(dx) && isFinite(dy)) {
                    result.left += Number(dx);
                    result.right += Number(dx);
                    result.top += Number(dy);
                    result.bottom += Number(dy)
                }
                return result
            },
            inflate: function(dx, dy) {
                var result = this.clone();
                if (isFinite(dx) && isFinite(dy)) {
                    result.left -= Number(dx);
                    result.right += Number(dx);
                    result.top -= Number(dy);
                    result.bottom += Number(dy)
                }
                return result
            },
            scale: function(factor) {
                var self = this;
                if (factor > 0)
                    return self.inflate(self.width() * (factor - 1) / 2, self.height() * (factor - 1) / 2);
                return self.clone()
            }
        })
    })(DevExpress);
    /*! Module viz-core, file themes.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            core = viz.core;
        var currentThemeId = 0;
        var findThemeId = function(themeName) {
                var themeId,
                    themes = viz.themes;
                for (themeId = 0; themeId < themes.length; themeId++)
                    if (themes[themeId].name === themeName)
                        return themeId;
                return -1
            };
        core.findTheme = function(themeName) {
            var themeId = findThemeId(themeName),
                themes = viz.themes;
            if (themeId < 0)
                themeId = currentThemeId;
            return themes[themeId]
        };
        core.currentTheme = function(themeName, colorScheme) {
            var themeId = -1,
                themes = viz.themes;
            if (themeName === undefined)
                return themes[currentThemeId].name;
            else {
                if (colorScheme)
                    themeId = findThemeId(themeName + '-' + colorScheme);
                if (themeId < 0)
                    themeId = findThemeId(themeName);
                currentThemeId = themeId >= 0 ? themeId : 0
            }
        };
        core.registerTheme = function(theme, basedOnThemeName) {
            var baseTheme,
                extendedTheme,
                themes = viz.themes;
            if (!theme || !theme.name || !core.findTheme(theme.name))
                return;
            baseTheme = core.findTheme(basedOnThemeName);
            if (baseTheme) {
                extendedTheme = $.extend(true, {}, baseTheme, theme);
                themes.push(extendedTheme)
            }
            else
                themes.push(theme)
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file palette.js */
    (function($, DX, undefined) {
        var core = DX.viz.core;
        core.palettes = {
            'default': ['#5F8B95', '#BA4D51', '#AF8A53', '#955F71', '#859666', '#7E688C'],
            'harmony light': ['#FCB65E', '#679EC5', '#AD79CE', '#A6C567', '#E18E92', '#DDED6E', '#B7ABEA', '#A8E7E3'],
            'soft pastel': ['#7CBAB4', '#92C7E2', '#75B5D6', '#B78C9B', '#F2CA84', '#A7CA74'],
            pastel: ['#bb7862', '#a4d5c2', '#bb626a', '#057d85', '#a12135', '#f5e7c9', '#153459', '#b1d2c6'],
            bright: ['#70c92f', '#f8ca00', '#e97f02', '#bd1550', '#800969', '#7e4452', '#9ab57e', '#36a3a6'],
            soft: ['#ebdd8f', '#9ab57e', '#e55253', '#7e4452', '#e8c267', '#565077', '#6babac', '#7e4452'],
            ocean: ['#75c099', '#cff499', '#378a8a', '#a5dda5', '#064970', '#38c5d2', '#00a7c6', '#a2cefb'],
            vintage: ['#ebb192', '#f2d1b5', '#cb715e', '#eb9692', '#a85c4c', '#f2c0b5', '#f6ead7', '#dd956c'],
            'vintage_desktop-dark': ['#e4a58b', '#edc4a8', '#be7060', '#e48e8b', '#9d5f51', '#edb2a8', '#f3e3cb', '#dd956c'],
            violet: ['#d1a1d1', '#f5ccdb', '#7b5685', '#7e7cad', '#55263f', '#5b41ab', '#d9d3d9', '#689cc1']
        };
        core.findPalette = function(paletteName, theme) {
            paletteName = String(paletteName).toLowerCase();
            theme && (theme = String(theme).toLowerCase());
            var basePalette = core.palettes[paletteName];
            return core.palettes[paletteName + '_' + theme] || basePalette
        };
        core.registerPalette = function(paletteName, palette, theme) {
            paletteName = String(paletteName).toLowerCase();
            theme && (paletteName = paletteName + '_' + String(theme).toLowerCase());
            return core.palettes[paletteName] = palette
        };
        function RingBuf(buf) {
            var ind = 0;
            this.next = function() {
                var res = buf[ind++];
                if (ind == buf.length)
                    this.reset();
                return res
            };
            this.reset = function() {
                ind = 0
            }
        }
        core.Palette = DX.Class.inherit({
            ctor: function(palette, stepHighlight, theme) {
                var self = this;
                self.currentColor = 0;
                self.stepHighlight = stepHighlight || 0;
                if ($.isArray(palette))
                    self.originalPalette = palette;
                else {
                    self.originalPalette = core.findPalette(palette, theme);
                    if (!self.originalPalette)
                        self.originalPalette = core.palettes['default']
                }
                self.palette = self.originalPalette.slice(0);
                self.paletteActions = new RingBuf(['highlight', 'highlight', 'darken', 'darken'])
            },
            dispose: function() {
                this.originalPalette = null;
                this.palette = null;
                this.paletteActions = null
            },
            getNextColor: function() {
                var self = this,
                    palette = self.palette,
                    color = palette[self.currentColor],
                    action;
                self.currentColor++;
                if (self.currentColor >= palette.length) {
                    self.currentColor = 0;
                    if (self.stepHighlight) {
                        action = self.paletteActions.next();
                        for (var i = 0; i < palette.length; i++)
                            palette[i] = new DX.Color(palette[i])[action](self.stepHighlight)
                    }
                }
                return color
            },
            reset: function() {
                this.currentColor = 0;
                this.palette = this.originalPalette.slice(0);
                this.paletteActions.reset()
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file baseThemeManager.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            IE8 = 'IE8';
        core.BaseThemeManager = DX.Class.inherit({
            ctor: function(userTheme, themeGroupName) {
                userTheme = userTheme || {};
                var _this = this,
                    themeName = typeof userTheme === 'string' ? userTheme : userTheme.name,
                    theme = core.findTheme(themeName);
                _this.themeName = theme.name;
                _this.font = $.extend(true, {}, theme.font, userTheme.font || {});
                if (themeGroupName && theme)
                    $.each(themeGroupName.split('.'), function() {
                        if (_this.isIE8)
                            theme[this + IE8] && $.extend(true, theme[this], theme[this + IE8]);
                        theme = theme[this]
                    });
                _this.theme = $.extend(true, {}, theme || {}, typeof userTheme === 'string' ? {} : userTheme)
            },
            dispose: function() {
                this.font = this.theme = this.themeName = null
            },
            initializeFont: function(fontOptions) {
                $.extend(fontOptions, this.font, $.extend({}, fontOptions))
            },
            applyTheme: function(theme, userOptions) {
                return $.extend(true, {}, theme, userOptions || {})
            },
            getTheme: function() {
                return this.theme
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file textCloud.js */
    (function(DX, undefined) {
        var min = Math.min;
        DX.viz.core.TextCloud = DX.Class.inherit(function() {
            var DEFAULT_OPTIONS = {
                    horMargin: 8,
                    verMargin: 4,
                    tailLength: 10
                };
            var COEFFICIENTS_MAP = {};
            COEFFICIENTS_MAP['right-bottom'] = COEFFICIENTS_MAP['rb'] = [0, -1, -1, 0, 0, 1, 1, 0];
            COEFFICIENTS_MAP['bottom-right'] = COEFFICIENTS_MAP['br'] = [-1, 0, 0, -1, 1, 0, 0, 1];
            COEFFICIENTS_MAP['left-bottom'] = COEFFICIENTS_MAP['lb'] = [0, -1, 1, 0, 0, 1, -1, 0];
            COEFFICIENTS_MAP['bottom-left'] = COEFFICIENTS_MAP['bl'] = [1, 0, 0, -1, -1, 0, 0, 1];
            COEFFICIENTS_MAP['left-top'] = COEFFICIENTS_MAP['lt'] = [0, 1, 1, 0, 0, -1, -1, 0];
            COEFFICIENTS_MAP['top-left'] = COEFFICIENTS_MAP['tl'] = [1, 0, 0, 1, -1, 0, 0, -1];
            COEFFICIENTS_MAP['right-top'] = COEFFICIENTS_MAP['rt'] = [0, 1, -1, 0, 0, -1, 1, 0];
            COEFFICIENTS_MAP['top-right'] = COEFFICIENTS_MAP['tr'] = [-1, 0, 0, 1, 1, 0, 0, -1];
            return {
                    setup: function(options) {
                        var self = this,
                            ops = $.extend({}, DEFAULT_OPTIONS, options),
                            x = ops.x,
                            y = ops.y,
                            type = COEFFICIENTS_MAP[ops.type],
                            cloudWidth = ops.textWidth + 2 * ops.horMargin,
                            cloudHeight = ops.textHeight + 2 * ops.verMargin,
                            tailWidth = ops.tailLength,
                            tailHeight = tailWidth,
                            cx = x,
                            cy = y;
                        if (type[0] & 1)
                            tailHeight = min(tailHeight, cloudHeight / 3);
                        else
                            tailWidth = min(tailWidth, cloudWidth / 3);
                        self._points = [x, y, x += type[0] * (cloudWidth + tailWidth), y += type[1] * (cloudHeight + tailHeight), x += type[2] * cloudWidth, y += type[3] * cloudHeight, x += type[4] * cloudWidth, y += type[5] * cloudHeight, x += type[6] * (cloudWidth - tailWidth), y += type[7] * (cloudHeight - tailHeight)];
                        self._cx = cx + type[0] * tailWidth + (type[0] + type[2]) * cloudWidth / 2;
                        self._cy = cy + type[1] * tailHeight + (type[1] + type[3]) * cloudHeight / 2;
                        self._cloudWidth = cloudWidth;
                        self._cloudHeight = cloudHeight;
                        self._tailLength = ops.tailLength;
                        return self
                    },
                    points: function() {
                        return this._points.slice(0)
                    },
                    cx: function() {
                        return this._cx
                    },
                    cy: function() {
                        return this._cy
                    },
                    width: function() {
                        return this._cloudWidth
                    },
                    height: function() {
                        return this._cloudHeight
                    },
                    tailLength: function() {
                        return this._tailLength
                    }
                }
        }())
    })(DevExpress);
    /*! Module viz-core, file parseUtils.js */
    (function($, DX) {
        var viz = DX.viz,
            core = viz.core,
            Class = DX.Class,
            isDefined = DX.utils.isDefined;
        var parseUtils = Class.inherit({
                ctor: function(options) {
                    options = options || {};
                    this._incidentOccured = $.isFunction(options.incidentOccured) ? options.incidentOccured : $.noop
                },
                correctValueType: function(type) {
                    return type === 'numeric' || type === 'datetime' || type === 'string' ? type : ''
                },
                _parsers: {
                    string: function(val) {
                        return isDefined(val) ? '' + val : val
                    },
                    numeric: function(val) {
                        if (!isDefined(val))
                            return val;
                        var parsedVal = Number(val);
                        if (isNaN(parsedVal))
                            parsedVal = undefined;
                        return parsedVal
                    },
                    datetime: function(val) {
                        if (!isDefined(val))
                            return val;
                        var parsedVal,
                            numVal = Number(val);
                        if (!isNaN(numVal))
                            parsedVal = new Date(numVal);
                        else
                            parsedVal = new Date(val);
                        if (isNaN(Number(parsedVal)))
                            parsedVal = undefined;
                        return parsedVal
                    }
                },
                getParser: function(valueType, entity) {
                    var self = this,
                        parser,
                        message = 'valueType is unknown.';
                    if (entity)
                        message = 'The type specified as the "valueType" field of the ' + entity + ' configuration object is unknown.';
                    valueType = self.correctValueType(valueType);
                    parser = self._parsers[valueType];
                    if (!parser)
                        this._incidentOccured.call(null, message);
                    return parser || $.noop
                }
            });
        core.ParseUtils = parseUtils
    })(jQuery, DevExpress);
    /*! Module viz-core, file loadIndicatorAPI.js */
    (function($, DX) {
        var viz = DX.viz,
            core = viz.core;
        var LoadIndicator = DX.Class.inherit({
                ctor: function(options, canvas) {
                    options = options || {};
                    this.$canvas = $(canvas);
                    this._updateContainer()
                },
                _updateRenderer: function() {
                    if (this._renderer)
                        this._renderer.recreateCanvas(this.canvasWidth, this.canvasHeight);
                    else if (this.image[0]) {
                        this._renderer = new viz.renderers.Renderer({
                            width: this.canvasWidth,
                            height: this.canvasHeight
                        });
                        this._renderer.draw(this.image[0])
                    }
                    return this._renderer
                },
                _draw: function(renderer) {
                    var baseLineSettings,
                        yellow = 0,
                        color;
                    if (!this._group && renderer) {
                        this._group = renderer.createGroup();
                        baseLineSettings = {
                            stroke: 'red',
                            strokeWidth: 3,
                            fill: 'red',
                            opacity: 1
                        };
                        for (var i = 0; i < 360; i += 20) {
                            color = 'rgb(255, ' + (yellow += i / 10) + ', 0)';
                            baseLineSettings.stroke = color;
                            baseLineSettings.fill = color;
                            baseLineSettings.rotate = -i;
                            renderer.createLine(0, -35, 0, -22, baseLineSettings).append(this._group)
                        }
                        this._group.append()
                    }
                    else if (this._group) {
                        this._group.move(this.canvasWidth / 2, this.canvasHeight / 2);
                        this._group.animate({rotate: {
                                angle: 360,
                                x: 0,
                                y: 0
                            }}, {
                            easing: 'linear',
                            repeatCount: Infinity
                        })
                    }
                },
                _updateContainer: function(width, height) {
                    var imageTop,
                        renderer;
                    width = width || this.$canvas.width();
                    height = height || this.$canvas.height();
                    this.container = this.container || $('<div>', {css: {position: 'relative'}}).appendTo(this.$canvas);
                    if (this.$canvas[0])
                        imageTop = this.$canvas.offset().top - this.container.offset().top;
                    else
                        imageTop = -height;
                    if (this.canvasWidth !== width || this.canvasHeight !== height) {
                        if (this.image)
                            this.image.css({
                                top: imageTop,
                                width: width,
                                height: height
                            });
                        else if (!this.image) {
                            this.container.hide();
                            this.image = $('<div>', {css: {
                                    position: 'absolute',
                                    left: 0,
                                    top: imageTop,
                                    width: width,
                                    height: height,
                                    backgroundColor: '#ffffff',
                                    opacity: 0.85
                                }}).appendTo(this.container)
                        }
                        this.canvasWidth = width;
                        this.canvasHeight = height;
                        renderer = this._updateRenderer()
                    }
                    this._draw(renderer)
                },
                show: function(width, height) {
                    this.container.show();
                    this._updateContainer(width, height)
                },
                hide: function() {
                    this.container.hide();
                    this._renderer && this._renderer.stopAllAnimations()
                }
            });
        core.loadIndicatorAPI = {
            base: {
                showLoadIndicator: function() {
                    var canvas = this.canvas || {};
                    this._loadIndicator = this._loadIndicator || new LoadIndicator({}, this._element()[0]);
                    this._loadIndicator.show(canvas.width, canvas.height)
                },
                hideLoadIndicator: function() {
                    this._loadIndicator && this._loadIndicator.hide()
                }
            },
            gauge: {
                showLoadIndicator: function() {
                    var canvas = this._getCanvas() || {};
                    this._loadIndicator = this._loadIndicator || new LoadIndicator({}, this._element()[0]);
                    this._loadIndicator.show(canvas.width, canvas.height)
                },
                hideLoadIndicator: function() {
                    this._loadIndicator && this._loadIndicator.hide()
                }
            }
        };
        core._LoadIndicator = LoadIndicator;
        core.__setMockLoadIndicator = function(mockLoadIndicator) {
            LoadIndicator = mockLoadIndicator
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file default.js */
    (function($, DX, undefined) {
        DX.viz.themes = DX.viz.themes || [];
        var fontFamilyDefault = "'Segoe UI', 'Helvetica Neue', 'Trebuchet MS', Verdana",
            fontFamilyLight = "'Segoe UI Light', 'Helvetica Neue Light', 'Segoe UI', 'Helvetica Neue', 'Trebuchet MS', Verdana";
        DX.viz.themes.push({
            name: 'desktop',
            font: {
                color: '#808080',
                opacity: 0.75,
                family: fontFamilyDefault,
                weight: 400,
                size: 12,
                cursor: 'default'
            },
            chart: {
                containerBackgroundColor: '#ffffff',
                defaultPalette: 'default',
                commonSeriesSettings: {
                    border: {
                        visible: false,
                        width: 2
                    },
                    hoverMode: 'excludePoints',
                    selectionMode: 'includePoints',
                    hoverStyle: {
                        hatching: {
                            direction: 'right',
                            width: 2,
                            step: 6,
                            opacity: 0.75
                        },
                        border: {
                            visible: false,
                            width: 3
                        }
                    },
                    selectionStyle: {
                        hatching: {
                            direction: 'right',
                            width: 2,
                            step: 6,
                            opacity: 0.5
                        },
                        border: {
                            visible: false,
                            width: 3
                        }
                    },
                    point: {
                        visible: true,
                        symbol: 'circle',
                        size: 6,
                        border: {
                            visible: false,
                            width: 1
                        },
                        hoverMode: 'onlyPoint',
                        selectionMode: 'onlyPoint',
                        hoverStyle: {
                            border: {
                                visible: true,
                                width: 4
                            },
                            size: 6
                        },
                        selectionStyle: {
                            border: {
                                visible: true,
                                width: 4
                            },
                            size: 6
                        }
                    },
                    label: {
                        font: {
                            color: '#ffffff',
                            opacity: 1
                        },
                        border: {
                            visible: false,
                            width: 1,
                            color: '#808080',
                            dashStyle: 'solid'
                        },
                        connector: {
                            visible: false,
                            width: 1
                        }
                    },
                    scatter: {},
                    line: {
                        width: 2,
                        dashStyle: 'solid',
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3}
                    },
                    stackedline: {
                        width: 2,
                        dashStyle: 'solid',
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3}
                    },
                    fullstackedline: {
                        width: 2,
                        dashStyle: 'solid',
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3}
                    },
                    stepline: {
                        width: 2,
                        dashStyle: 'solid',
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3}
                    },
                    area: {point: {visible: false}},
                    stackedarea: {point: {visible: false}},
                    fullstackedarea: {point: {visible: false}},
                    steparea: {
                        border: {
                            visible: true,
                            width: 2
                        },
                        point: {visible: false},
                        hoverStyle: {border: {
                                visible: true,
                                width: 3
                            }},
                        selectionStyle: {border: {
                                visible: true,
                                width: 3
                            }}
                    },
                    spline: {
                        width: 2,
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3}
                    },
                    splinearea: {point: {visible: false}},
                    bar: {
                        cornerRadius: 0,
                        point: {
                            hoverStyle: {border: {visible: false}},
                            selectionStyle: {border: {visible: false}}
                        }
                    },
                    stackedbar: {
                        cornerRadius: 0,
                        point: {
                            hoverStyle: {border: {visible: false}},
                            selectionStyle: {border: {visible: false}}
                        }
                    },
                    fullstackedbar: {
                        cornerRadius: 0,
                        point: {
                            hoverStyle: {border: {visible: false}},
                            selectionStyle: {border: {visible: false}}
                        }
                    },
                    rangebar: {
                        cornerRadius: 0,
                        point: {
                            hoverStyle: {border: {visible: false}},
                            selectionStyle: {border: {visible: false}}
                        }
                    },
                    rangearea: {point: {visible: false}},
                    rangesplinearea: {point: {visible: false}},
                    pie: {
                        border: {
                            visible: false,
                            width: 2,
                            color: '#ffffff'
                        },
                        hoverStyle: {
                            hatching: {
                                direction: 'right',
                                width: 4,
                                step: 10,
                                opacity: 0.75
                            },
                            border: {
                                visible: false,
                                width: 2
                            }
                        },
                        selectionStyle: {
                            hatching: {
                                direction: 'right',
                                width: 4,
                                step: 10,
                                opacity: 0.5
                            },
                            border: {
                                visible: false,
                                width: 2
                            }
                        }
                    },
                    doughnut: {innerRadius: 0.5},
                    bubble: {opacity: 0.5},
                    candlestick: {
                        width: 1,
                        innerColor: '#ffffff',
                        reduction: {color: '#ff0000'},
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3}
                    },
                    stock: {
                        width: 1,
                        reduction: {color: '#ff0000'},
                        hoverStyle: {
                            width: 3,
                            hatching: {direction: 'none'}
                        },
                        selectionStyle: {width: 3}
                    }
                },
                legend: {
                    verticalAlignment: 'top',
                    horizontalAlignment: 'right',
                    position: 'outside',
                    font: {color: '#808080'},
                    visible: true,
                    customizeText: undefined,
                    itemTextPosition: undefined,
                    margin: 20,
                    equalColumnWidth: false,
                    markerSize: 12,
                    backgroundColor: undefined,
                    border: {
                        visible: false,
                        width: 1,
                        color: '#808080',
                        cornerRadius: 0,
                        opacity: 0.35,
                        dashStyle: 'solid'
                    },
                    paddingLeftRight: 20,
                    paddingTopBottom: 15,
                    columnCount: 0,
                    rowCount: 0,
                    columnItemSpacing: 20,
                    rowItemSpacing: 8
                },
                tooltip: {
                    enabled: false,
                    font: {
                        family: fontFamilyLight,
                        weight: 200,
                        size: 26,
                        color: '#ffffff'
                    },
                    shared: false,
                    arrowLength: 10,
                    paddingLeftRight: 22,
                    paddingTopBottom: 6,
                    format: '',
                    argumentFormat: '',
                    precision: 0,
                    argumentPrecision: 0,
                    percentPrecision: 0,
                    customizeText: undefined
                },
                title: {font: {
                        family: fontFamilyLight,
                        weight: 200,
                        color: '#232323',
                        size: 28,
                        opacity: 1
                    }},
                crosshair: {
                    enabled: false,
                    color: '#808080',
                    width: 1,
                    dashStyle: 'solid',
                    opacity: 0.45,
                    verticalLine: {visible: true},
                    horizontalLine: {visible: true}
                },
                commonAxisSettings: {
                    discreteAxisDivisionMode: 'betweenLabels',
                    visible: false,
                    color: '#808080',
                    opacity: 0.35,
                    width: 1,
                    multipleAxesSpacing: 5,
                    label: {
                        visible: true,
                        overlappingBehavior: {
                            mode: 'auto',
                            rotationAngle: 90,
                            staggeringSpacing: 5
                        },
                        precision: 0,
                        format: '',
                        customizeText: undefined,
                        indentFromAxis: 10
                    },
                    grid: {
                        visible: false,
                        color: '#808080',
                        opacity: 0.35,
                        width: 1
                    },
                    tick: {
                        visible: false,
                        color: '#808080',
                        opacity: 0.35
                    },
                    title: {
                        font: {size: 16},
                        margin: 10
                    },
                    stripStyle: {
                        paddingLeftRight: 10,
                        paddingTopBottom: 5
                    },
                    constantLineStyle: {
                        paddingLeftRight: 10,
                        paddingTopBottom: 10,
                        width: 1,
                        color: '#000000',
                        dashStyle: 'solid',
                        label: {
                            visible: true,
                            position: 'inside'
                        }
                    }
                },
                horizontalAxis: {
                    isHorizontal: true,
                    position: 'bottom',
                    axisDivisionFactor: 50,
                    label: {alignment: "center"},
                    stripStyle: {label: {
                            horizontalAlignment: 'center',
                            verticalAlignment: 'top'
                        }},
                    constantLineStyle: {label: {
                            horizontalAlignment: 'right',
                            verticalAlignment: 'top'
                        }},
                    constantLines: {}
                },
                verticalAxis: {
                    isHorizontal: false,
                    position: 'left',
                    axisDivisionFactor: 30,
                    label: {
                        alignment: 'right',
                        overlappingBehavior: {mode: 'enlargeTickInterval'}
                    },
                    stripStyle: {label: {
                            horizontalAlignment: 'left',
                            verticalAlignment: 'center'
                        }},
                    constantLineStyle: {label: {
                            horizontalAlignment: 'left',
                            verticalAlignment: 'top'
                        }},
                    constantLines: {}
                },
                argumentAxisStyle: {},
                valueAxisStyle: {grid: {visible: true}},
                commonPaneSettings: {border: {
                        color: '#808080',
                        opacity: 0.35,
                        width: 1
                    }},
                dataPrepareSettings: {
                    checkTypeForAllData: false,
                    convertToAxisDataType: true,
                    sortingMethod: true
                },
                useAggregation: false
            },
            chartIE8: {commonSeriesSettings: {pie: {
                        hoverStyle: {border: {
                                visible: true,
                                color: '#ffffff'
                            }},
                        selectionStyle: {border: {
                                visible: true,
                                color: '#ffffff'
                            }}
                    }}},
            gauge: {
                containerBackgroundColor: '#ffffff',
                scale: {
                    majorTick: {color: '#ffffff'},
                    minorTick: {color: '#ffffff'},
                    label: {font: {color: '#7f7f7f'}}
                },
                rangeContainer: {
                    backgroundColor: '#808080',
                    palette: ['#ad79ce', '#639ec6', '#a5c763', '#ffb65a', '#e78e94']
                },
                valueIndicator: {
                    _default: {color: '#c2c2c2'},
                    rangebar: {
                        color: '#ad79ce',
                        backgroundColor: 'none',
                        text: {font: {
                                size: 14,
                                color: null
                            }}
                    },
                    twocolorneedle: {secondColor: '#e18e92'},
                    twocolorrectangle: {secondColor: '#e18e92'}
                },
                subvalueIndicator: {
                    _default: {color: '#679ec5'},
                    textcloud: {text: {font: {
                                color: '#ffffff',
                                size: 18
                            }}}
                },
                title: {font: {
                        size: 18,
                        color: '#232323',
                        family: fontFamilyLight,
                        weight: 200
                    }},
                subtitle: {font: {
                        size: 14,
                        color: '#232323',
                        family: fontFamilyLight,
                        weight: 200
                    }},
                indicator: {text: {font: {
                            color: '#7f7f7f',
                            size: 18
                        }}},
                tooltip: {font: {
                        color: '#ffffff',
                        size: 26,
                        family: fontFamilyLight,
                        weight: 200
                    }}
            },
            barGauge: {
                valueIndicator: {
                    palette: ['#a6c567', '#679ec5', '#ad79ce', '#fcb65e', '#e18e92'],
                    backgroundColor: '#808080',
                    text: {font: {color: null}}
                },
                title: {font: {
                        size: 18,
                        color: '#232323',
                        family: fontFamilyLight,
                        weight: 200
                    }},
                subtitle: {font: {
                        size: 14,
                        color: '#232323',
                        family: fontFamilyLight,
                        weight: 200
                    }},
                tooltip: {font: {
                        color: '#ffffff',
                        size: 26,
                        family: fontFamilyLight,
                        weight: 200
                    }},
                indicator: {text: {font: {
                            color: '#7f7f7f',
                            size: 18
                        }}}
            },
            rangeSelector: {
                containerBackgroundColor: '#ffffff',
                scale: {
                    label: {
                        topIndent: 7,
                        font: {size: 11}
                    },
                    tick: {
                        width: 1,
                        color: '#000000',
                        opacity: 0.1
                    },
                    marker: {
                        separatorHeight: 33,
                        topIndent: 10,
                        textLeftIndent: 7,
                        textTopIndent: 11
                    }
                },
                sliderMarker: {
                    padding: 7,
                    pointerSize: 6,
                    color: '#9b9b9b',
                    invalidRangeColor: '#ff0000',
                    font: {
                        color: '#ffffff',
                        size: 11
                    }
                },
                sliderHandle: {
                    width: 1,
                    color: '#000000',
                    opacity: 0.1
                },
                shutter: {
                    color: undefined,
                    opacity: 0.75
                },
                background: {color: "#c0bae1"},
                chart: {
                    containerBackgroundColor: undefined,
                    defaultPalette: 'default',
                    commonSeriesSettings: {
                        border: {
                            visible: false,
                            width: 1
                        },
                        hoverStyle: {border: {}},
                        selectionStyle: {border: {}},
                        point: {
                            visible: false,
                            symbol: 'circle',
                            border: {
                                visible: false,
                                width: 1
                            },
                            size: 6,
                            hoverStyle: {border: {}},
                            selectionStyle: {border: {}}
                        },
                        line: {width: 2},
                        stackedline: {width: 2},
                        fullstackedline: {width: 2},
                        area: {},
                        stackedarea: {},
                        fullstackedarea: {},
                        spline: {width: 2},
                        splinearea: {},
                        bar: {cornerRadius: 0},
                        stackedbar: {cornerRadius: 0},
                        fullstackedbar: {cornerRadius: 0},
                        rangebar: {cornerRadius: 0},
                        rangearea: {},
                        rangesplinearea: {},
                        pie: {},
                        candlestick: {
                            width: 1,
                            innerColor: '#ffffff',
                            reduction: {color: '#ff0000'}
                        },
                        stock: {
                            width: 1,
                            reduction: {color: '#ff0000'}
                        }
                    },
                    dataPrepareSettings: {
                        checkTypeForAllData: false,
                        convertToAxisDataType: true,
                        sortingMethod: true
                    },
                    useAggregation: false
                }
            },
            map: {
                background: {
                    borderWidth: 1,
                    borderColor: '#cacaca',
                    color: '#ffffff'
                },
                area: {
                    borderWidth: 1,
                    borderColor: '#ffffff',
                    color: '#d2d2d2',
                    hoveredBorderWidth: 1,
                    hoveredBorderColor: '#303030',
                    selectedBorderWidth: 2,
                    selectedBorderColor: '#303030',
                    hoveredClass: 'dxm-area-hovered',
                    selectedClass: 'dxm-area-selected'
                },
                marker: {
                    borderWidth: 2,
                    borderColor: '#ffffff',
                    color: '#ba4d51',
                    size: 4,
                    extraSize: 13,
                    font: {
                        color: '#2b2b2b',
                        opacity: null,
                        size: 12
                    },
                    hoveredClass: 'dxm-marker-hovered',
                    selectedClass: 'dxm-marker-selected',
                    extraColor: '#ffffff',
                    extraOpacity: 0.32
                },
                controlBar: {
                    borderColor: '#5d5d5d',
                    borderWidth: 3,
                    color: '#ffffff'
                },
                tooltip: {
                    borderWidth: 1,
                    borderColor: '#d7d7d7',
                    color: '#ffffff',
                    font: {
                        color: '#2b2b2b',
                        opacity: null,
                        size: 14
                    }
                },
                legend: {
                    horizontalIndent: 10,
                    verticalIndent: 10,
                    horizontalPadding: 16,
                    verticalPadding: 12,
                    maxWidth: 400,
                    maxHeight: 400,
                    textIndent: 8,
                    itemSpacing: 4,
                    itemSize: 12,
                    borderWidth: 1,
                    borderColor: '#cacaca',
                    opacity: 0.65,
                    color: '#ffffff',
                    font: {
                        color: '#2b2b2b',
                        opacity: null,
                        size: 12
                    }
                }
            },
            sparkline: {
                lineColor: '#666666',
                lineWidth: 2,
                areaOpacity: 0.2,
                minColor: '#e8c267',
                maxColor: '#e55253',
                barPositiveColor: '#a9a9a9',
                barNegativeColor: '#d7d7d7',
                winColor: '#a9a9a9',
                lossColor: '#d7d7d7',
                firstLastColor: '#666666',
                pointSymbol: 'circle',
                pointColor: '#ffffff',
                pointSize: 2,
                tooltip: {
                    enabled: true,
                    allowContainerResizing: true,
                    verticalAlignment: 'top',
                    horizontalAlignment: 'center',
                    format: '',
                    paddingLeftRight: 14,
                    paddingTopBottom: 10,
                    arrowLength: 10,
                    precision: 0,
                    color: '#666666',
                    opacity: 0.9,
                    font: {
                        color: '#ffffff',
                        family: 'Segoe UI',
                        opacity: 1,
                        size: 12,
                        weight: 200
                    }
                }
            },
            bullet: {
                color: '#e8c267',
                targetColor: '#666666',
                targetWidth: 4,
                showTarget: true,
                showZeroLevel: true,
                tooltip: {
                    enabled: true,
                    allowContainerResizing: true,
                    verticalAlignment: 'top',
                    horizontalAlignment: 'center',
                    format: '',
                    precision: 0,
                    paddingLeftRight: 14,
                    paddingTopBottom: 10,
                    arrowLength: 10,
                    color: '#666666',
                    opacity: 0.9,
                    font: {
                        color: '#ffffff',
                        family: 'Segoe UI',
                        opacity: 1,
                        size: 12,
                        weight: 200
                    }
                }
            }
        });
        DX.viz.core.registerTheme({
            name: 'desktop-dark',
            rangeSelector: {
                shutter: {
                    color: '#2b2b2b',
                    opacity: 0.9
                },
                sliderMarker: {
                    color: '#b5b5b5',
                    font: {
                        color: '#303030',
                        opacity: 1
                    }
                },
                sliderHandles: {
                    color: '#ffffff',
                    opacity: 0.35
                },
                scale: {
                    label: {font: {
                            color: '#6f6f6f',
                            opacity: 1,
                            size: 11
                        }},
                    tick: {
                        color: '#ffffff',
                        opacity: 0.05
                    }
                }
            },
            gauge: {
                valueIndicator: {
                    _default: {color: '#b5b5b5'},
                    twocolorneedle: {secondColor: '#ba544d'},
                    twocolorrectangle: {secondColor: '#ba544d'}
                },
                subvalueIndicator: {_default: {color: '#ba544d'}},
                containerBackgroundColor: '#303030',
                scale: {
                    majorTick: {color: '#303030'},
                    minorTick: {color: '#303030'},
                    label: {font: {
                            color: '#6f6f6f',
                            opacity: 1,
                            weight: 'Normal'
                        }}
                },
                rangeContainer: {backgroundColor: '#b5b5b5'},
                title: {font: {
                        color: '#b5b5b5',
                        opacity: 1
                    }}
            },
            sparkline: {
                lineColor: '#c7c7c7',
                firstLastColor: '#c7c7c7',
                barPositiveColor: '#b8b8b8',
                barNegativeColor: '#8e8e8e',
                winColor: '#b8b8b8',
                lossColor: '#8e8e8e',
                pointColor: '#303030',
                tooltip: {
                    color: '#c7c7c7',
                    font: {color: '#303030'}
                }
            },
            bullet: {
                targetColor: '#8e8e8e',
                tooltip: {
                    color: '#c7c7c7',
                    font: {color: '#303030'}
                }
            },
            map: {
                background: {
                    borderColor: '#3f3f3f',
                    color: '#303030'
                },
                area: {
                    borderColor: '#303030',
                    color: '#686868',
                    hoveredBorderColor: '#ffffff',
                    selectedBorderColor: '#ffffff'
                },
                marker: {font: {color: '#ffffff'}},
                controlBar: {
                    borderColor: '#c7c7c7',
                    color: '#303030'
                },
                legend: {
                    borderColor: '#3f3f3f',
                    color: '#303030',
                    font: {color: '#ffffff'}
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file android.js */
    (function($, DX, undefined) {
        DX.viz.core.registerTheme({
            name: 'android',
            chart: {
                title: {font: {color: '#ffffff'}},
                commonAxisSettings: {
                    title: {font: {color: '#6f6f6f'}},
                    label: {font: {
                            color: '#ffffff',
                            size: 11,
                            opacity: 1
                        }},
                    grid: {
                        color: '#4c4c4c',
                        opacity: 1
                    }
                },
                legend: {font: {
                        color: '#ffffff',
                        opacity: 1,
                        size: 11
                    }}
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file ios.js */
    (function($, DX, undefined) {
        DX.viz.core.registerTheme({
            name: 'ios',
            chart: {
                title: {font: {color: '#808080'}},
                commonAxisSettings: {
                    title: {font: {color: '#6f6f6f'}},
                    label: {font: {
                            color: '#000000',
                            size: 11,
                            opacity: 1
                        }},
                    grid: {
                        color: '#808080',
                        opacity: 0.35
                    }
                },
                legend: {font: {
                        color: '#000000',
                        opacity: 1,
                        size: 11
                    }}
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file win8.js */
    (function($, DX) {
        DX.viz.core.registerTheme({
            name: 'win8',
            chart: {
                title: {font: {color: '#ffffff'}},
                commonAxisSettings: {
                    title: {font: {color: '#6f6f6f'}},
                    label: {font: {
                            color: '#ffffff',
                            size: 11,
                            opacity: 1
                        }},
                    grid: {
                        color: '#4c4c4c',
                        opacity: 0.9
                    }
                },
                legend: {font: {
                        color: '#ffffff',
                        opacity: 1,
                        size: 11
                    }}
            }
        });
        DX.viz.core.registerTheme({
            name: 'win8-white',
            chart: {
                title: {font: {color: '#808080'}},
                commonAxisSettings: {
                    title: {font: {color: '#6f6f6f'}},
                    label: {font: {
                            color: '#000000',
                            size: 11,
                            opacity: 0.75
                        }},
                    grid: {
                        color: '#808080',
                        opacity: 0.35
                    }
                },
                legend: {font: {
                        color: '#000000',
                        opacity: 1,
                        size: 11
                    }}
            }
        }, 'win8')
    })(jQuery, DevExpress);
    /*! Module viz-core, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz.renderers = {}
    })(DevExpress);
    /*! Module viz-core, file svgRenderer.js */
    (function($, DX) {
        var renderers = DX.viz.renderers,
            utils = DX.utils,
            Class = DX.Class,
            doc = document,
            MAX_PIXEL_COUNT = 10000000000;
        function createElement(name) {
            return doc.createElementNS('http://www.w3.org/2000/svg', name)
        }
        var BaseSvgElement = Class.inherit({
                ctor: function baseSvgElementCtor(renderer, name, params) {
                    this.renderer = renderer;
                    this.element = this.createElement(name);
                    this.$element = $(this.element);
                    this.applySettings($.extend({}, this.defaultSettings(), params));
                    this.__passedParams = params
                },
                defaultSettings: $.noop,
                createElement: function(nodeName) {
                    this._nodeName = nodeName;
                    return createElement(nodeName)
                },
                dispose: function() {
                    this.off();
                    this.remove();
                    this.renderer = null;
                    this.element = null;
                    this.settings = null;
                    this.$element = null;
                    this.transformation = null;
                    this.__passedParams = null;
                    this.__appliedSettings = null;
                    this.__appliedStyle = null
                },
                append: function(svgElement) {
                    var toElement = svgElement || this.renderer.getRoot();
                    toElement.element.appendChild(this.element);
                    return this
                },
                insertBefore: function(target) {
                    target.element.parentNode.insertBefore(this.element, target.element);
                    return this
                },
                toBackground: function() {
                    this.element.parentNode && this.element.parentNode.insertBefore(this.element, this.element.parentNode.firstChild);
                    return this
                },
                toForeground: function() {
                    this.element.parentNode && this.element.parentNode.appendChild(this.element);
                    return this
                },
                addClass: function(className) {
                    var classAttribute = this.$element.attr('class'),
                        classNameIndex,
                        classNames;
                    if (className) {
                        if (classAttribute) {
                            classNames = classAttribute.split(' ');
                            classNameIndex = $.inArray(className, classNames);
                            if (classNameIndex === -1)
                                classAttribute += ' ' + className
                        }
                        else
                            classAttribute = className;
                        this.$element.attr('class', classAttribute)
                    }
                    return this.$element
                },
                removeClass: function(className) {
                    var classAttribute = this.$element.attr('class'),
                        classNames,
                        indexDeleteElement,
                        resultClassNames = '',
                        i;
                    if (classAttribute && className) {
                        classNames = classAttribute.split(' ');
                        indexDeleteElement = $.inArray(className, classNames);
                        if (indexDeleteElement !== -1) {
                            for (i = 0; i < classNames.length; i++)
                                if (i !== indexDeleteElement)
                                    resultClassNames += classNames[i] + ' ';
                            this.$element.attr('class', resultClassNames.replace(/ $/, ''))
                        }
                    }
                    return this.$element
                },
                applySettings: function(settings) {
                    var normalized;
                    this.settings = $.extend(this.settings || {}, settings || {});
                    this.adjustSettings();
                    normalized = this._normalizeSettings(this.settings);
                    this.applyStyle(this._style);
                    this._applyAttributes(normalized);
                    return this
                },
                _applyAttributes: function(settings) {
                    this.$element.attr(settings);
                    this.__appliedSettings = settings
                },
                adjustSettings: function(){},
                applyStyle: function(style) {
                    this.$element.css(style || {});
                    this.__appliedStyle = style || {};
                    return this
                },
                trigger: function(event, data) {
                    this.$element.trigger(event, data)
                },
                on: function(events, data, handler) {
                    this.$element.on.apply(this.$element, arguments);
                    return this
                },
                data: function(data) {
                    this.$element.data(data);
                    return this
                },
                removeData: function() {
                    this.$element.removeData();
                    return this
                },
                off: function(events) {
                    this.$element.off(events);
                    return this
                },
                getBBox: function() {
                    var self = this,
                        bBox,
                        element = this.element,
                        transformation = self.transformation,
                        rotateAngle = transformation.rotateAngle || 0,
                        rotateX = transformation.rotateX || 0,
                        rotateY = transformation.rotateY || 0,
                        mabs = Math.abs,
                        mmin = Math.min;
                    function bBox(el) {
                        var ret = {};
                        try {
                            if (!$.isFunction(el.getBBox))
                                throw{};
                            else
                                ret = el.getBBox()
                        }
                        catch(e) {
                            ret = {
                                x: 0,
                                y: 0,
                                width: el.offsetWidth || 0,
                                height: el.offsetHeight || 0
                            }
                        }
                        return ret
                    }
                    bBox = $.extend({}, bBox(element));
                    if (rotateAngle) {
                        var cossin = utils.getCosAndSin(rotateAngle),
                            sin = cossin.sin.toFixed(3),
                            cos = cossin.cos.toFixed(3),
                            ltx = bBox.x - rotateX,
                            lty = bBox.y - rotateY,
                            rtx = bBox.x + bBox.width - rotateX,
                            rty = bBox.y - rotateY,
                            lbx = bBox.x - rotateX,
                            lby = bBox.y + bBox.height - rotateY,
                            rbx = bBox.x + bBox.width - rotateX,
                            rby = bBox.y + bBox.height - rotateY,
                            w,
                            h;
                        w = mabs(bBox.height * sin) + mabs(bBox.width * cos);
                        h = mabs(bBox.height * cos) + mabs(bBox.width * sin);
                        bBox.x = mmin(ltx * cos - lty * sin + rotateX, rtx * cos - rty * sin + rotateX, lbx * cos - lby * sin + rotateX, rbx * cos - rby * sin + rotateX);
                        bBox.y = mmin(ltx * sin + lty * cos + rotateY, rtx * sin + rty * cos + rotateY, lbx * sin + lby * cos + rotateY, rbx * sin + rby * cos + rotateY);
                        bBox.width = w;
                        bBox.height = h
                    }
                    return self._normalizeBBox(bBox)
                },
                _normalizeBBox: function(bBox) {
                    var ceil = Math.ceil,
                        floor = Math.floor,
                        $isNumeric = $.isNumeric,
                        rxl = floor(bBox.x),
                        ryt = floor(bBox.y),
                        rxr = ceil(bBox.width + bBox.x),
                        ryb = ceil(bBox.height + bBox.y),
                        width,
                        height;
                    bBox.x = $isNumeric(rxl) && rxl < MAX_PIXEL_COUNT && rxl > -MAX_PIXEL_COUNT ? rxl : 0;
                    bBox.y = $isNumeric(ryt) && ryt < MAX_PIXEL_COUNT && ryt > -MAX_PIXEL_COUNT ? ryt : 0;
                    width = rxr - rxl;
                    height = ryb - ryt;
                    bBox.width = $isNumeric(width) && width < MAX_PIXEL_COUNT && width > -MAX_PIXEL_COUNT ? width : 0;
                    bBox.height = $isNumeric(height) && height < MAX_PIXEL_COUNT && height > -MAX_PIXEL_COUNT ? height : 0;
                    bBox.isEmpty = !bBox.x && !bBox.y && !bBox.width && !bBox.height;
                    return bBox
                },
                clear: function(selector) {
                    selector ? this.$element.find(selector).remove() : this.$element.empty()
                },
                detach: function() {
                    this.$element.detach()
                },
                animate: function(params, options, complete) {
                    options = options || {};
                    var _this = this,
                        animationParams = {};
                    if (complete)
                        $.extend(options, {complete: complete});
                    if (this.renderer.animOptions.enabled) {
                        $.each(params, function(name, to) {
                            switch (name) {
                                case'scale':
                                    animationParams['transform'] = animationParams['transform'] || {};
                                    var scale = _this.transformation.scale || {};
                                    animationParams['transform'].scale = {
                                        x: {
                                            from: utils.isDefined(scale.x) ? scale.x : 1,
                                            to: utils.isDefined(to.x) ? to.x : 1
                                        },
                                        y: {
                                            from: utils.isDefined(scale.y) ? scale.y : 1,
                                            to: utils.isDefined(to.y) ? to.y : 1
                                        }
                                    };
                                    break;
                                case'rotate':
                                    animationParams['transform'] = animationParams['transform'] || {};
                                    animationParams['transform'].rotate = {
                                        angle: {
                                            from: _this.transformation.rotateAngle || 0,
                                            to: to.angle
                                        },
                                        y: to.y || 0,
                                        x: to.x || 0
                                    };
                                    break;
                                case'translate':
                                    animationParams['transform'] = animationParams['transform'] || {};
                                    animationParams['transform'].translate = {
                                        x: {
                                            from: _this.transformation.translateX || 0,
                                            to: to.x || 0
                                        },
                                        y: {
                                            from: _this.transformation.translateY || 0,
                                            to: to.y || 0
                                        }
                                    };
                                    break;
                                case'points':
                                    animationParams[name] = to;
                                    break;
                                default:
                                    animationParams[name] = {
                                        from: _this.settings[name] || 0,
                                        to: to
                                    }
                            }
                        });
                        _this.renderer.animateElement(_this, animationParams, $.extend({}, this.renderer.animOptions, options))
                    }
                    else {
                        if (params.translate) {
                            if ('x' in params.translate)
                                params.translateX = params.translate.x;
                            if ('y' in params.translate)
                                params.translateY = params.translate.y;
                            delete params.translate
                        }
                        if (options) {
                            options.step && options.step.call(_this, 1, 1);
                            options.complete && options.complete.call(_this)
                        }
                        this.applySettings(params)
                    }
                },
                stopAnimation: function() {
                    var self = this;
                    self.animation && self.animation.stop(true);
                    return self
                },
                move: function(x, y, animate, animOptions) {
                    x = x || 0,
                    y = y || 0;
                    animOptions = animOptions || {};
                    if (!animate)
                        this.applySettings({
                            translateX: x,
                            translateY: y
                        });
                    else
                        this.animate({translate: {
                                x: x,
                                y: y
                            }}, animOptions);
                    return this
                },
                rotate: function(angle, x, y, animate, animOptions) {
                    angle = angle || 0;
                    x = x || 0;
                    y = y || 0;
                    animOptions = animOptions || {};
                    if (!animate)
                        this.applySettings({rotate: [angle, x, y]});
                    else
                        this.animate({rotate: {
                                angle: angle,
                                x: x,
                                y: y
                            }}, animOptions)
                },
                remove: function() {
                    this.$element.remove()
                },
                _normalizeSettings: function(settings) {
                    var key,
                        style,
                        firstChar,
                        styleName,
                        prop,
                        value,
                        normalized = {},
                        fontSetting;
                    for (key in settings) {
                        prop = key,
                        value = settings[prop];
                        if (prop === 'align') {
                            prop = 'text-anchor';
                            value = {
                                left: 'start',
                                center: 'middle',
                                right: 'end'
                            }[value]
                        }
                        else if (prop === 'font') {
                            style = this['_style'] = this['_style'] || {};
                            if (!$.isPlainObject(value))
                                continue;
                            $.each(value, function(fontSetting) {
                                switch (fontSetting) {
                                    case'color':
                                        styleName = 'fill';
                                        break;
                                    case'opacity':
                                        styleName = 'fillOpacity';
                                        break;
                                    case'cursor':
                                        styleName = fontSetting;
                                        break;
                                    default:
                                        firstChar = fontSetting.charAt(0);
                                        styleName = 'font' + fontSetting.replace(firstChar, firstChar.toUpperCase())
                                }
                                style[styleName] = value[fontSetting]
                            });
                            continue
                        }
                        else if (prop === 'dashStyle') {
                            prop = 'stroke-dasharray';
                            value = value.toLowerCase();
                            value = value === 'solid' ? 'none' : value.replace(/longdash/g, '8,3,').replace(/dash/g, '4,3,').replace(/dot/g, '1,3,').replace(/,$/, '').split(',');
                            if (value !== 'none')
                                value = $.map(value, function(p) {
                                    return +p * (settings.strokeWidth || 1)
                                }).join(',')
                        }
                        else if (/^(linecap|linejoin)$/i.test(prop))
                            prop = 'stroke-' + prop;
                        else if (/^(translateX|translateY|rotate|scale)$/i.test(prop)) {
                            this['_' + prop] = value;
                            continue
                        }
                        else if (prop === 'clipId') {
                            prop = 'clip-path';
                            value = 'url(#' + value + ')'
                        }
                        else if (prop === 'style') {
                            this['_style'] = this['_style'] || {};
                            $.extend(true, this['_style'], value);
                            continue
                        }
                        else if (prop === 'text')
                            continue;
                        else if (prop === 'segments')
                            continue;
                        else
                            prop = DX.inflector.dasherize(prop);
                        normalized[prop] = value
                    }
                    return this._applyTransformation(normalized)
                },
                _applyTransformation: function(settings) {
                    this.transformation = {
                        translateX: this._translateX,
                        translateY: this._translateY,
                        rotateAngle: 0,
                        rotateX: 0,
                        rotateY: 0
                    };
                    var tr = this.transformation,
                        rotate = this._rotate,
                        scale = this._scale,
                        transformations = [];
                    if (utils.isDefined(tr.translateX) || utils.isDefined(tr.translateY))
                        transformations.push('translate(' + (tr.translateX || 0) + ',' + (tr.translateY || 0) + ')');
                    if (utils.isDefined(rotate)) {
                        if (utils.isNumber(rotate)) {
                            tr.rotateAngle = rotate;
                            tr.rotateX = settings.x || 0;
                            tr.rotateY = settings.y || 0
                        }
                        else if ($.isArray(rotate)) {
                            tr.rotateAngle = rotate[0] || 0;
                            tr.rotateX = rotate[1] || 0;
                            tr.rotateY = rotate[2] || 0
                        }
                        else if (utils.isObject(rotate)) {
                            tr.rotateAngle = rotate.angle || 0;
                            tr.rotateX = rotate.x || 0;
                            tr.rotateY = rotate.y || 0
                        }
                        transformations.push('rotate(' + tr.rotateAngle + ',' + tr.rotateX + ',' + tr.rotateY + ')')
                    }
                    if (utils.isNumber(scale)) {
                        var value = utils.isDefined(scale) ? scale : 1;
                        transformations.push('scale(' + value + ',' + value + ')');
                        tr.scale = {
                            x: value,
                            y: value
                        }
                    }
                    else if (utils.isObject(scale)) {
                        var valueX = utils.isDefined(scale.x) ? scale.x : 1;
                        var valueY = utils.isDefined(scale.y) ? scale.y : 1;
                        transformations.push('scale(' + valueX + ',' + valueY + ')');
                        tr.scale = {
                            x: valueX,
                            y: valueY
                        }
                    }
                    if (transformations.length)
                        settings.transform = transformations.join(' ');
                    return settings
                }
            });
        var RootSvgElement = BaseSvgElement.inherit({
                defaultSettings: function() {
                    return {
                            width: 0,
                            height: 0,
                            style: {'-webkit-tap-highlight-color': 'rgba(0, 0, 0, 0)'},
                            xmlns: 'http://www.w3.org/2000/svg',
                            'xmlns:xlink': 'http://www.w3.org/1999/xlink',
                            version: '1.1',
                            stroke: 'none',
                            strokeWidth: 0,
                            fill: 'none'
                        }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'svg', params)
                }
            });
        var RectSvgBaseElement = {
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0,
                            width: 0,
                            height: 0
                        }
                },
                adjustSettings: function() {
                    if (!utils.isDefined(this.settings.sharpEdges) || this.settings.sharpEdges) {
                        this.sharpEdges();
                        delete this.settings.sharpEdges
                    }
                },
                prepareSettings: function(settings) {
                    var prevStrokeWidth = this.settings ? Number(this.settings.strokeWidth) || 0 : 0,
                        newStrokeWidth,
                        maxStrokeWidth,
                        strokeWidthChanged = false;
                    if (utils.isDefined(settings.width))
                        this._realWidth = Number(settings.width);
                    if (utils.isDefined(settings.height))
                        this._realHeight = Number(settings.height);
                    if (utils.isDefined(settings.x))
                        this._realX = Number(settings.x);
                    if (utils.isDefined(settings.y))
                        this._realY = Number(settings.y);
                    if (utils.isDefined(settings.strokeWidth))
                        this._realStrokeWidth = Number(settings.strokeWidth);
                    this._realStrokeWidth = this._realStrokeWidth || this.defaultSettings().strokeWidth || 0;
                    maxStrokeWidth = ~~((this._realWidth < this._realHeight ? this._realWidth : this._realHeight) / 2);
                    newStrokeWidth = this._realStrokeWidth < maxStrokeWidth ? this._realStrokeWidth : maxStrokeWidth;
                    if (newStrokeWidth !== prevStrokeWidth) {
                        strokeWidthChanged = true;
                        settings.sharpEdges = true;
                        newStrokeWidth > 0 && (settings.strokeWidth = newStrokeWidth)
                    }
                    (utils.isDefined(settings.x) || strokeWidthChanged) && (settings.x = this._realX + newStrokeWidth / 2);
                    (utils.isDefined(settings.y) || strokeWidthChanged) && (settings.y = this._realY + newStrokeWidth / 2);
                    (utils.isDefined(settings.width) || strokeWidthChanged) && (settings.width = this._realWidth - newStrokeWidth);
                    (utils.isDefined(settings.height) || strokeWidthChanged) && (settings.height = this._realHeight - newStrokeWidth)
                },
                applySettings: function(settings) {
                    var settings = $.extend(true, {}, settings);
                    this.prepareSettings(settings);
                    this.callBase(settings)
                },
                sharpEdges: function() {
                    var strokeWidth = Math.round(this.settings.strokeWidth || 0),
                        correction = strokeWidth % 2 / 2;
                    this.settings.x = Math.floor(this.settings.x - correction || 0) + correction;
                    this.settings.y = Math.floor(this.settings.y - correction || 0) + correction;
                    this.settings.width = Math.floor(this.settings.width || 0);
                    this.settings.height = Math.floor(this.settings.height || 0);
                    this.settings.strokeWidth > 0 && (this.settings.strokeWidth = strokeWidth)
                }
            };
        var ImageSvgElement = BaseSvgElement.inherit(RectSvgBaseElement).inherit({
                ctor: function(renderer, params, href, location) {
                    var locationToPreserveAspectRatioMap = {
                            full: 'none',
                            lefttop: 'xMinYMin',
                            leftcenter: 'xMinYMid',
                            leftbottom: 'xMinYMax',
                            centertop: 'xMidYMin',
                            center: 'xMidYMid',
                            centerbottom: 'xMidYMax',
                            righttop: 'xMaxYMin',
                            rightcenter: 'xMaxYMid',
                            rightbottom: 'xMaxYMax'
                        };
                    this.href = utils.isDefined(href) ? href : '';
                    this.preserveAspectRatio = locationToPreserveAspectRatioMap[(location || '').toLowerCase()];
                    this.preserveAspectRatio = this.preserveAspectRatio || 'none';
                    this.callBase(renderer, 'image', params)
                },
                adjustSettings: function() {
                    this.callBase();
                    this.element.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.href);
                    if (this.preserveAspectRatio)
                        this.element.setAttribute('preserveAspectRatio', this.preserveAspectRatio)
                }
            });
        var RectSvgElement = BaseSvgElement.inherit(RectSvgBaseElement).inherit({
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0,
                            width: 0,
                            height: 0,
                            rx: 0,
                            ry: 0
                        }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'rect', params)
                }
            });
        var PathSvgElement = BaseSvgElement.inherit({
                defaultSettings: function() {
                    return {points: {
                                x: 0,
                                y: 0
                            }}
                },
                getNodeName: function() {
                    return 'path'
                },
                getPathAttributeName: function() {
                    return 'd'
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, this.getNodeName(), params)
                },
                dispose: function() {
                    this.segments = null;
                    this.fromSegments = null;
                    this.callBase()
                },
                adjustSettings: function() {
                    this.prepareSegments(this.settings)
                },
                applySettings: function(settings) {
                    var settings = settings || {};
                    if (this.settings && settings.strokeWidth && this.settings.strokeWidth !== settings.strokeWidth)
                        settings.sharpEdges = true;
                    this.callBase(settings)
                },
                prepareSegments: function(params) {
                    if ('points' in params) {
                        var points = params.points,
                            firstElem = points[0],
                            close = this.closePath || params.closePath,
                            segments = [],
                            i;
                        if (utils.isObject(firstElem))
                            segments = $.map(points, function(pt, i) {
                                if (!pt)
                                    return null;
                                if (!i)
                                    return [['M', pt.x, pt.y]];
                                return [['L', pt.x, pt.y]]
                            });
                        else if (utils.isNumber(firstElem))
                            for (i = 0; i < points.length; i += 2) {
                                if (!i) {
                                    segments = [['M', points[i] || 0, points[i + 1] || 0]];
                                    continue
                                }
                                segments.push(['L', points[i] || 0, points[i + 1] || 0])
                            }
                        else
                            segments = [['M', 0, 0]];
                        if (close)
                            segments.push(['Z']);
                        this.segments = segments;
                        delete params.points;
                        delete params.closePath;
                        params.sharpEdges = true
                    }
                    if (params.sharpEdges) {
                        this.sharpEdges();
                        this.combinePathParams(params);
                        delete params.sharpEdges
                    }
                },
                customizeSegments: function(segments) {
                    return segments
                },
                combinePathParams: function(params) {
                    var path;
                    this.segments = this.customizeSegments(this.segments);
                    if (this.segments) {
                        path = $.map(this.segments, function(seg, i) {
                            return seg.join(' ')
                        });
                        path = path.join(' ');
                        params[this.getPathAttributeName()] = path
                    }
                },
                animate: function(params, options, complete) {
                    var _this = this;
                    if (!('points' in params) || !this.renderer.animOptions.enabled)
                        return this.callBase(params, options, complete);
                    var fromPath = _this.segments;
                    _this.prepareSegments(params);
                    delete params.d;
                    if (fromPath.length === _this.segments.length)
                        params.points = {
                            from: fromPath,
                            to: _this.segments
                        };
                    _this.callBase(params, options, complete)
                },
                sharpEdges: function() {
                    var self = this,
                        segLength = self.segments.length,
                        i = 0,
                        curSeg,
                        nextSeg,
                        curX,
                        curY,
                        nextX,
                        nextY,
                        curXIdx,
                        curYIdx,
                        nextXIdx,
                        nextYIdx,
                        strokeWidth = Math.round(self.settings.strokeWidth || 0),
                        correction = strokeWidth % 2 / 2;
                    for (i; i < segLength - 1; i++) {
                        curSeg = self.segments[i];
                        nextSeg = self.segments[i + 1];
                        if (nextSeg[0] === 'Z' && i)
                            nextSeg = self.segments[0];
                        switch (curSeg[0]) {
                            case'M':
                            case'L':
                                curXIdx = 1;
                                curYIdx = 2;
                                break;
                            case'C':
                                curXIdx = 5;
                                curYIdx = 6;
                                break;
                            case'A':
                                curXIdx = 6;
                                curYIdx = 7;
                                break;
                            case'Z':
                                continue
                        }
                        switch (nextSeg[0]) {
                            case'M':
                            case'L':
                                nextXIdx = 1;
                                nextYIdx = 2;
                                break;
                            case'C':
                                nextXIdx = 5;
                                nextYIdx = 6;
                                break;
                            case'A':
                                nextXIdx = 6;
                                nextYIdx = 7;
                                break;
                            case'Z':
                                continue
                        }
                        curX = Math.floor(curSeg[curXIdx]);
                        curY = Math.floor(curSeg[curYIdx]);
                        nextX = nextSeg[nextXIdx] = Math.floor(nextSeg[nextXIdx]);
                        nextY = nextSeg[nextYIdx] = Math.floor(nextSeg[nextYIdx]);
                        curSeg[curXIdx] = i == 0 ? curX : curSeg[curXIdx];
                        curSeg[curYIdx] = i == 0 ? curY : curSeg[curYIdx];
                        if (curX == nextX) {
                            curSeg[curXIdx] = curX + correction;
                            nextSeg[nextXIdx] = nextX + correction
                        }
                        if (curY == nextY) {
                            curSeg[curYIdx] = curY + correction;
                            nextSeg[nextYIdx] = nextY + correction
                        }
                    }
                }
            });
        var SegmentRectSvgElement = PathSvgElement.inherit(RectSvgBaseElement).inherit({
                defaultSettings: function() {
                    return $.extend(true, {}, this.callBase(), {segments: {
                                top: true,
                                bottom: true,
                                left: true,
                                right: true
                            }})
                },
                prepareSegments: function() {
                    var self = this,
                        settings = self.settings,
                        left = settings.x,
                        right = left + settings.width,
                        top = settings.y,
                        bottom = top + settings.height,
                        segments = [],
                        segmentSequence,
                        visiblyOpt = 0,
                        prevSegmentVisibility = 0;
                    var allSegment = {
                            top: [['M', left, top], ['L', right, top]],
                            right: [['M', right, top], ['L', right, bottom]],
                            bottom: [['M', right, bottom], ['L', left, bottom]],
                            left: [['M', left, bottom], ['L', left, top]]
                        };
                    $.each(allSegment, function(seg, _) {
                        var visibility = !!self.settings.segments[seg];
                        visiblyOpt = visiblyOpt * 2 + ~~visibility
                    });
                    switch (visiblyOpt) {
                        case(13):
                        case(9):
                            segmentSequence = ['left', 'top', 'right', 'bottom'];
                            break;
                        case(11):
                            segmentSequence = ['bottom', 'left', 'top', 'right'];
                            break;
                        default:
                            segmentSequence = ['top', 'right', 'bottom', 'left']
                    }
                    $.each(segmentSequence, function(_, seg) {
                        var segmentVisibility = !!self.settings.segments[seg];
                        if (segmentVisibility)
                            $.each(allSegment[seg].slice(prevSegmentVisibility), function(_, segment) {
                                segments.push(segment)
                            });
                        prevSegmentVisibility = ~~segmentVisibility
                    });
                    visiblyOpt == 15 && segments.push(['Z']);
                    this.segments = segments.length ? segments : [['M', 0, 0], ['Z']];
                    this.combinePathParams(settings)
                },
                adjustSettings: function() {
                    this.callBase();
                    this.prepareSegments()
                },
                applySettings: function(settings) {
                    var segments = this.settings && this.settings.segments || this.defaultSettings().segments;
                    settings.segments = $.extend(true, {}, segments || {}, settings.segments);
                    this.callBase(settings)
                }
            });
        var AreaSvgElement = PathSvgElement.inherit({
                defaultSettings: function() {
                    return {points: {
                                x: 0,
                                y: 0
                            }}
                },
                ctor: function(renderer, params) {
                    this.closePath = true;
                    this.callBase(renderer, params)
                }
            });
        var BezierSvgElement = PathSvgElement.inherit({
                defaultSettings: function() {
                    return {points: {
                                x: 0,
                                y: 0
                            }}
                },
                prepareSegments: function(params) {
                    if (!('points' in params))
                        return;
                    var points = params.points,
                        firstElem = points[0],
                        close = this.closePath || params.closePath,
                        segments = [],
                        seg = [],
                        i,
                        x,
                        y;
                    var cnt = 0;
                    if (utils.isObject(firstElem)) {
                        for (i = 0; i < points.length; i++) {
                            x = points[i].x;
                            y = points[i].y;
                            if (!i) {
                                segments = [['M', x, y]];
                                continue
                            }
                            if ((i - 1) % 3 == 0) {
                                if (seg.length > 0)
                                    segments.push(seg);
                                seg = ['C', x, y];
                                continue
                            }
                            seg.push(x);
                            seg.push(y)
                        }
                        if (seg.length > 0)
                            segments.push(seg)
                    }
                    else if (utils.isNumber(firstElem)) {
                        for (i = 0; i < points.length; i += 2) {
                            x = points[i];
                            y = points[i + 1];
                            if (!i) {
                                segments = [['M', x, y || 0]];
                                continue
                            }
                            if ((i - 2) % 6 == 0) {
                                if (seg.length > 0)
                                    segments.push(seg);
                                seg = ['C', x, y || 0];
                                continue
                            }
                            seg.push(x);
                            seg.push(y || 0)
                        }
                        if (seg.length > 0)
                            segments.push(seg)
                    }
                    else
                        segments = [['M', 0, 0]];
                    if (close)
                        segments.push(['Z']);
                    this.segments = segments;
                    delete params.points;
                    delete params.closePath;
                    this.combinePathParams(params)
                }
            });
        var BezierAreaSvgElement = BezierSvgElement.inherit({
                defaultSettings: function() {
                    return {points: {
                                x: 0,
                                y: 0
                            }}
                },
                ctor: function(renderer, params) {
                    this.closePath = true;
                    this.callBase(renderer, params)
                }
            });
        var ArcSvgElement = PathSvgElement.inherit({
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0,
                            linejoin: 'round'
                        }
                },
                createArcSegments: function(x, y, innerR, outerR, startAngle, endAngle, isCircle) {
                    var longFlag = Math.abs(endAngle - startAngle) > Math.PI ? '1' : '0',
                        xOuterStart = x + outerR * Math.cos(startAngle),
                        yOuterStart = y - outerR * Math.sin(startAngle),
                        xOuterEnd = x + outerR * Math.cos(endAngle),
                        yOuterEnd = y - outerR * Math.sin(endAngle),
                        xInnerStart = x + innerR * Math.cos(endAngle),
                        yInnerStart = y - innerR * Math.sin(endAngle),
                        xInnerEnd = x + innerR * Math.cos(startAngle),
                        yInnerEnd = y - innerR * Math.sin(startAngle);
                    return [['M', xOuterStart, yOuterStart], ['A', outerR, outerR, 0, longFlag, 0, xOuterEnd, yOuterEnd], [isCircle ? 'M' : 'L', xInnerStart, yInnerStart], ['A', innerR, innerR, 0, longFlag, 1, xInnerEnd, yInnerEnd], ['Z']]
                },
                prepareSegments: function(params) {
                    if (!('x' in params) && !('y' in params) && !('outerRadius' in params) && !('innerRadius' in params) && !('startAngle' in params) && !('endAngle' in params))
                        return;
                    var x = utils.isNumber(params.x) ? Number(params.x) : 0,
                        y = utils.isNumber(params.y) ? Number(params.y) : 0,
                        outerR = utils.isNumber(params.outerRadius) ? Number(params.outerRadius) : 0,
                        innerR = utils.isNumber(params.innerRadius) ? Number(params.innerRadius) : 0,
                        startAngle = utils.isNumber(params.startAngle) ? Number(params.startAngle) : 0,
                        endAngle = utils.isNumber(params.endAngle) ? Number(params.endAngle) : 360,
                        isCircle;
                    this.segments = [['M', 0, 0], ['Z']];
                    if (outerR || innerR) {
                        var tmp = Math.min(outerR, innerR);
                        outerR = Math.max(outerR, innerR);
                        innerR = tmp;
                        if (Math.round(startAngle) != Math.round(endAngle)) {
                            if (Math.abs(endAngle - startAngle) % 360 == 0) {
                                startAngle = 0;
                                endAngle = 360;
                                isCircle = true;
                                endAngle -= 0.0001
                            }
                            if (startAngle > 360)
                                startAngle = startAngle % 360;
                            if (endAngle > 360)
                                endAngle = endAngle % 360;
                            if (startAngle > endAngle)
                                startAngle -= 360;
                            startAngle = startAngle * Math.PI / 180;
                            endAngle = endAngle * Math.PI / 180;
                            this.segments = this.createArcSegments(x, y, innerR, outerR, startAngle, endAngle, isCircle)
                        }
                    }
                    delete params.x;
                    delete params.y;
                    delete params.outerRadius;
                    delete params.innerRadius;
                    delete params.startAngle;
                    delete params.endAngle;
                    this.combinePathParams(params)
                }
            });
        var CircleSvgElement = BaseSvgElement.inherit({
                defaultSettings: function() {
                    return {
                            cx: 0,
                            cy: 0,
                            r: 0
                        }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'circle', params)
                }
            });
        var TextSvgElement = BaseSvgElement.inherit({
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0
                        }
                },
                ctor: function(renderer, params) {
                    this.tspans = [];
                    this.callBase(renderer, 'text', params)
                },
                dispose: function() {
                    this.tspans = null;
                    this.callBase()
                },
                updateText: function(text) {
                    if (!utils.isDefined(text))
                        text = '';
                    this.applySettings({text: text})
                },
                adjustSettings: function() {
                    if (!('text' in this.settings)) {
                        this.changeX();
                        return
                    }
                    this._createElementWithText(this.settings.text)
                },
                changeX: function() {
                    for (var i = 0; i < this.tspans.length; i++)
                        if (this.tspans[i].settings.x != undefined)
                            this.tspans[i].applySettings({x: this.settings.x})
                },
                _createElementWithText: function(text) {
                    var div,
                        i;
                    this.clear();
                    text = text.toString().replace(/\r/g, "");
                    text = text.replace(/\n/g, "<br/>");
                    div = doc.createElement("div");
                    div.innerHTML = text;
                    div.params = {style: {}};
                    this._orderText(div)
                },
                clear: function() {
                    this.callBase();
                    this.tspans = []
                },
                _orderText: function(node) {
                    var textArray = [],
                        defaultFontSize = (this.settings.font ? this.settings.font.size : 12) || 12;
                    var order = function(strCount, node, textArray) {
                            var params = {style: {}},
                                textArray = textArray || [];
                            node.params = node.params || {};
                            if (node.parentNode && node.nodeName != "#text")
                                if (node.parentNode.params)
                                    for (var i in node.parentNode.params)
                                        node.params[i] = node.parentNode.params[i];
                            switch (node.tagName) {
                                case"B" || "STRONG":
                                    node.params.fontWeight = "bold";
                                    break;
                                case"I" || "EM":
                                    node.params.fontStyle = "italic";
                                    break;
                                case"U":
                                    node.params.textDecoration = "underline";
                                    break;
                                case"BR":
                                    strCount++;
                                    break
                            }
                            if (node.style) {
                                if (node.style.fontSize)
                                    node.params.fontSize = node.style.fontSize.split('p')[0] || node.params.fontSize;
                                node.params.fill = node.style.color || node.params.fill;
                                node.params.fontStyle = node.style.fontStyle || node.params.fontStyle;
                                node.params.fontWeight = node.style.fontWeight || node.params.fontWeight;
                                node.params.textDecoration = node.style.textDecoration || node.params.textDecoration
                            }
                            var childnum = node.childNodes.length;
                            var count = 0;
                            while (count != childnum)
                                strCount = order(strCount, node.childNodes[count++], textArray);
                            if (node.wholeText != undefined) {
                                params.fill = node.parentNode.params.fill;
                                params.text = node.wholeText,
                                node.parentNode.params.fontSize && (params.style.fontSize = node.parentNode.params.fontSize);
                                node.parentNode.params.fontStyle && (params.style.fontStyle = node.parentNode.params.fontStyle);
                                node.parentNode.params.fontWeight && (params.style.fontWeight = node.parentNode.params.fontWeight);
                                node.parentNode.params.textDecoration && (params.style.textDecoration = node.parentNode.params.textDecoration);
                                textArray.push({
                                    params: params,
                                    line: strCount
                                })
                            }
                            return strCount
                        };
                    order(0, node, textArray);
                    for (var txt = 0; txt < textArray.length; txt++) {
                        if (txt != 0)
                            if (textArray[txt].line != textArray[txt - 1].line) {
                                textArray[txt].params.dy = textArray[txt].params.fontSize || defaultFontSize;
                                textArray[txt].params.x = this.settings.x
                            }
                            else {
                                textArray[txt].params.dy = 0;
                                textArray[txt].params.dx = 0
                            }
                        else {
                            textArray[txt].params.x = this.settings.x;
                            textArray[txt].params.dy = 0
                        }
                        var tspan = new TspanSvgElement(this.renderer, textArray[txt].params);
                        tspan.append(this);
                        this.tspans.push(tspan)
                    }
                }
            });
        var TspanSvgElement = BaseSvgElement.inherit({ctor: function(renderer, params) {
                    var text = params.text || '';
                    delete params.text;
                    this.callBase(renderer, 'tspan', params);
                    this.element.appendChild(doc.createTextNode(text))
                }});
        var GroupSvgElement = BaseSvgElement.inherit({
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'g', params)
                },
                update: $.noop
            });
        var PatternSvgElement = BaseSvgElement.inherit({
                ctor: function(renderer, params) {
                    this.__patternParams = $.extend({}, params);
                    var id = utils.getNextPatternId(),
                        color = params.color,
                        hatching = params.hatching,
                        opacity = hatching.opacity,
                        width = hatching.width || 1,
                        step = hatching.step || 6,
                        direction = hatching.direction,
                        options = {
                            strokeWidth: width,
                            stroke: color
                        };
                    this.callBase(renderer, 'pattern', {
                        id: id,
                        width: step,
                        height: step
                    });
                    this.element.setAttribute('patternUnits', 'userSpaceOnUse');
                    this._rect = renderer.createRect(0, 0, step, step, 0, {
                        fill: color,
                        opacity: opacity
                    }).append(this);
                    this._path = renderer.createPath(0, options).append(this);
                    if (direction === 'right')
                        this._path.applySettings({d: "M " + step / 2 + " " + -step / 2 + " L " + -step / 2 + " " + step / 2 + "M 0 " + step + " L " + step + " 0 M " + step * 1.5 + " " + step / 2 + " L " + step / 2 + " " + step * 1.5});
                    else if (direction === 'left')
                        this._path.applySettings({d: "M 0 0 L " + step + ' ' + step + " M " + -step / 2 + " " + step / 2 + " L " + step / 2 + " " + step * 1.5 + " M " + step / 2 + -step / 2 + " L " + step * 1.5 + " " + step / 2});
                    this.id = 'url(#' + id + ')'
                },
                append: function() {
                    return this.callBase(this.renderer.defsSvg)
                },
                clear: function() {
                    this.callBase();
                    this._path = null
                },
                dispose: function() {
                    this._path = null;
                    this.callBase()
                }
            });
        var ClipRectSvgElement = BaseSvgElement.inherit({
                ctor: function(renderer, params) {
                    this.__clipRectParams = $.extend({}, params);
                    var x = params.x,
                        y = params.y,
                        w = params.w,
                        h = params.h,
                        id = utils.getNextClipId();
                    delete params.x;
                    delete params.y;
                    delete params.w;
                    delete params.h;
                    this.callBase(renderer, 'clipPath', {id: id});
                    this.id = id;
                    this._rect = renderer.createRect(x, y, w, h, 0, params);
                    this._rect.append(this)
                },
                append: function() {
                    return this.callBase(this.renderer.defsSvg)
                },
                updateRectangle: function(settings) {
                    this._rect.applySettings(settings)
                },
                dispose: function() {
                    this._rect = null;
                    this.callBase()
                }
            });
        var ShadowFilterSvgElement = BaseSvgElement.inherit({
                ctor: function(renderer) {
                    this.applySettings = $.noop;
                    this.callBase(renderer, 'filter');
                    delete this.applySettings;
                    this.ref = null;
                    this._create()
                },
                append: function() {
                    return this.callBase(this.renderer.defsSvg)
                },
                dispose: function() {
                    while (this.element.firstChild)
                        this.element.removeChild(this.element.firstChild);
                    this.callBase();
                    return this
                },
                applySettings: function(settings) {
                    settings = settings || {};
                    this.$element.attr({
                        id: settings.id || null,
                        x: settings.x || null,
                        y: settings.y || null,
                        width: settings.width || null,
                        height: settings.height || null
                    });
                    this.ref = settings.id ? 'url(#' + settings.id + ')' : null;
                    this._update(settings);
                    return this
                },
                _create: function() {
                    var gaussianBlur = this._gaussianBlur = createElement('feGaussianBlur'),
                        offset = this._offset = createElement('feOffset'),
                        colorMatrix = this._colorMatrix = createElement('feColorMatrix'),
                        blend = createElement('feBlend');
                    gaussianBlur.setAttribute('in', 'SourceGraphic');
                    gaussianBlur.setAttribute('result', 'result');
                    offset.setAttribute('in', 'result');
                    offset.setAttribute('result', 'result');
                    colorMatrix.setAttribute('in', 'result');
                    colorMatrix.setAttribute('result', 'result');
                    colorMatrix.setAttribute('type', 'matrix');
                    blend.setAttribute('in', 'SourceGraphic');
                    blend.setAttribute('in2', 'result');
                    blend.setAttribute('mode', 'normal');
                    this.element.appendChild(gaussianBlur);
                    this.element.appendChild(offset);
                    this.element.appendChild(colorMatrix);
                    this.element.appendChild(blend)
                },
                _update: function(settings) {
                    this._gaussianBlur.setAttribute('stdDeviation', settings.blur || 0);
                    this._offset.setAttribute('dx', settings.dx || 0);
                    this._offset.setAttribute('dy', settings.dy || 0);
                    this._colorMatrix.setAttribute('values', buildColorMatrixValues(settings.color, settings.opacity))
                }
            });
        function buildColorMatrixValues(color, opacity) {
            var c = new DX.Color(color || '#000000');
            return '0 0 0 ' + Number((c.r / 255).toFixed(2)) + ' 0 0 0 0 ' + Number((c.g / 255).toFixed(2)) + ' 0 0 0 0 ' + Number((c.b / 255).toFixed(2)) + ' 0 0 0 0 ' + (opacity || 1) + ' 0'
        }
        renderers.SvgRenderer = Class.inherit({
            ctor: function(options) {
                options = options || {};
                this._setAnimationOptions(options.animation || {});
                this.animationController = new renderers.AnimationController;
                this.cssClass = options.cssClass || '';
                this.recreateCanvas(options.width, options.height)
            },
            dispose: function() {
                this.killContainer();
                this.animationController.dispose();
                this.animOptions = null;
                this.animationController = null
            },
            _setAnimationOptions: function(options) {
                this.animOptions = {
                    enabled: true,
                    duration: 1000,
                    easing: 'easeOutCubic'
                };
                if ('enabled' in options)
                    this.animOptions.enabled = options.enabled;
                if ('duration' in options)
                    this.animOptions.duration = options.duration;
                if ('easing' in options && renderers.easingFunctions[options.easing])
                    this.animOptions.easing = options.easing
            },
            animationEnabled: function() {
                return !!this.animOptions.enabled
            },
            updateAnimationOptions: function(newOptions) {
                this._setAnimationOptions($.extend(this.animOptions || {}, newOptions))
            },
            stopAllAnimations: function() {
                this.animationController.stop()
            },
            killContainer: function() {
                this.svgRoot && (this.svgRoot.remove(), this.svgRoot = null);
                this.defsSvg && (this.defsSvg.remove(), this.defsSvg = null);
                this.drawn = null
            },
            recreateCanvas: function(width, height, cssClass) {
                if (width > 0 && height > 0) {
                    if (!this.svgRoot) {
                        this.cssClass = cssClass || this.cssClass;
                        this.svgRoot = new RootSvgElement(this, {
                            width: width,
                            height: height,
                            'class': this.cssClass
                        });
                        this.animationController.element = this.svgRoot.element
                    }
                    else
                        this.svgRoot.applySettings({
                            width: width,
                            height: height
                        });
                    this.defsSvg && this.defsSvg.clear("pattern")
                }
            },
            resize: function(width, height) {
                var root = this.getRoot();
                root && width > 0 && height > 0 && root.applySettings({
                    width: width,
                    height: height
                })
            },
            getRoot: function() {
                return this.svgRoot
            },
            isInitialized: function() {
                return !!this.svgRoot
            },
            draw: function(container) {
                if (!container || this.drawn)
                    return;
                container.appendChild(this.getRoot().element);
                this.drawn = true
            },
            updateParams: function(params, options) {
                if (options && options.strokeWidth)
                    params.strokeWidth = options.strokeWidth
            },
            animateElement: function(element, params, options) {
                this.animationController.animateElement(element, params, options)
            },
            createRect: function(x, y, w, h, r, options) {
                var params = {
                        x: x,
                        y: y,
                        width: w,
                        height: h,
                        rx: r,
                        ry: r
                    };
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new RectSvgElement(this, params)
            },
            createSegmentRect: function(x, y, w, h, r, segments, options) {
                var params = $.extend({}, options || {}, {
                        x: x,
                        y: y,
                        width: w,
                        height: h,
                        rx: r,
                        ry: r,
                        segments: segments
                    });
                return new SegmentRectSvgElement(this, params)
            },
            createClipRect: function(x, y, w, h) {
                var attr = {
                        x: x,
                        y: y,
                        w: w,
                        h: h,
                        fill: 'none',
                        stroke: 'none',
                        strokeWidth: 0
                    };
                if (!this.defsSvg) {
                    this.defsSvg = new BaseSvgElement(this, 'defs');
                    this.defsSvg.append()
                }
                return new ClipRectSvgElement(this, attr)
            },
            createPattern: function(color, hatching) {
                hatching = hatching || {};
                hatching.direction = (hatching.direction || '').toLowerCase();
                if (hatching.direction !== 'right' && hatching.direction !== 'left')
                    return {
                            id: color,
                            append: function() {
                                return this
                            },
                            clear: function(){},
                            dispose: function(){}
                        };
                if (!this.defsSvg) {
                    this.defsSvg = new BaseSvgElement(this, 'defs');
                    this.defsSvg.append()
                }
                return new PatternSvgElement(this, {
                        hatching: hatching,
                        color: color
                    })
            },
            createImage: function(x, y, w, h, href, options) {
                var params = $.extend({}, options || {}, {
                        x: x,
                        y: y,
                        width: w,
                        height: h
                    });
                return new ImageSvgElement(this, params, href, params.location)
            },
            createLine: function(x1, y1, x2, y2, options) {
                var params = {points: [x1, y1, x2, y2]};
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new PathSvgElement(this, params)
            },
            createPath: function(points, options) {
                var params = {points: points};
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new PathSvgElement(this, params)
            },
            createSimplePath: function(options) {
                return new BaseSvgElement(this, 'path', options)
            },
            createBezierPath: function(points, options) {
                var params = {points: points};
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new BezierSvgElement(this, params)
            },
            createArea: function(points, options) {
                var params = {points: points};
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new AreaSvgElement(this, params)
            },
            createBezierArea: function(points, options) {
                var params = {points: points};
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new BezierAreaSvgElement(this, params)
            },
            createCircle: function(x, y, r, options) {
                var params = {
                        cx: x,
                        cy: y,
                        r: r
                    };
                if (options && !options.inh)
                    $.extend(params, options);
                return new CircleSvgElement(this, params)
            },
            createArc: function(x, y, outerRadius, innerRadius, startAngle, endAngle, options) {
                var params = {
                        x: x,
                        y: y,
                        outerRadius: outerRadius,
                        innerRadius: innerRadius,
                        startAngle: startAngle,
                        endAngle: endAngle
                    };
                if (options && !options.inh)
                    $.extend(params, options);
                this.updateParams(params, options);
                return new ArcSvgElement(this, params)
            },
            createText: function(text, x, y, options) {
                var params = {
                        x: x,
                        y: y,
                        text: text
                    };
                if (options && !options.inh)
                    $.extend(params, options);
                return new TextSvgElement(this, params)
            },
            createGroup: function(options) {
                return new GroupSvgElement(this, options)
            },
            createFilter: function(type) {
                var filterType = type === 'shadow' ? ShadowFilterSvgElement : null;
                if (filterType) {
                    this.defsSvg = this.defSvg || new BaseSvgElement(this, 'defs').append();
                    return new filterType(this)
                }
                return null
            }
        });
        function buildPath(points) {
            var i = 0,
                ii = points.length,
                list = [];
            for (; i < ii; )
                list.push('L', points[i++].toFixed(2), points[i++].toFixed(2));
            if (ii) {
                list[0] = 'M';
                list.push('Z');
                list = list.join(' ')
            }
            else
                list = '';
            return list
        }
        renderers._svgBuildPath = buildPath;
        renderers._svgRendererInternals = {
            BaseSvgElement: BaseSvgElement,
            RootSvgElement: RootSvgElement,
            RectSvgElement: RectSvgElement,
            ImageSvgElement: ImageSvgElement,
            PathSvgElement: PathSvgElement,
            AreaSvgElement: AreaSvgElement,
            BezierSvgElement: BezierSvgElement,
            BezierAreaSvgElement: BezierAreaSvgElement,
            CircleSvgElement: CircleSvgElement,
            TextSvgElement: TextSvgElement,
            TspanSvgElement: TspanSvgElement,
            GroupSvgElement: GroupSvgElement,
            ArcSvgElement: ArcSvgElement,
            RectSvgBaseElement: RectSvgBaseElement,
            SegmentRectSvgElement: SegmentRectSvgElement,
            ClipRectSvgElement: ClipRectSvgElement,
            PatternSvgElement: PatternSvgElement,
            ShadowFilterSvgElement: ShadowFilterSvgElement
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file vmlRenderer.js */
    (function($, DX) {
        var renderers = DX.viz.renderers,
            utils = DX.utils,
            doc = document,
            svgRendererInternals = renderers._svgRendererInternals;
        var appendTimerID;
        var vmlElementsToAppend = [];
        var CSS_PROPERTIES = ['position', 'display', 'visibility', 'filter', 'margin', 'marginTop', 'marginLeft', 'marginRight', 'marginBottom', 'whiteSpace', 'clip', 'overflow'];
        var INHERITABLE_PROPERTIES = ['stroke', 'fill', 'opacity', 'strokeWidth', 'align'];
        var defaultVmlSettings = {
                x: 0,
                y: 0,
                width: 1,
                height: 1,
                position: 'absolute'
            };
        var extendDefaultVmlOptions = function(customOptions, baseOptions) {
                return $.extend(true, baseOptions || {}, defaultVmlSettings, customOptions)
            };
        var parseRotateParameter = function(rotate, defaultX, defaultY) {
                var rotateObject;
                if (utils.isDefined(rotate))
                    if (utils.isNumber(rotate))
                        rotateObject = {
                            angle: rotate,
                            x: defaultX || 0,
                            y: defaultY || 0
                        };
                    else if ($.isArray(rotate))
                        rotateObject = {
                            angle: rotate[0] || 0,
                            x: rotate[1] || 0,
                            y: rotate[2] || 0
                        };
                    else if (utils.isObject(rotate))
                        rotateObject = {
                            angle: rotate.angle || 0,
                            x: rotate.x || 0,
                            y: rotate.y || 0
                        };
                return rotateObject
            };
        var applySubElementAttribute = function(vmlElement, params, name) {
                var element = vmlElement.element,
                    subElement,
                    value = params[name];
                if (name === 'opacity' || name === 'fillOpacity')
                    if (element.fill)
                        element.fill.opacity = value >= 0.002 ? value : 0.002;
                    else {
                        subElement = doc.createElement('vml:fill');
                        element.appendChild(subElement);
                        subElement.opacity = value >= 0.002 ? value : 0.002;
                        subElement.className = 'vml';
                        if (params.fillcolor)
                            subElement.color = params.fillcolor
                    }
                if (name === 'joinStyle')
                    if (element.stroke)
                        element.stroke.joinStyle = value;
                    else {
                        subElement = doc.createElement('vml:stroke');
                        vmlElement.element.appendChild(subElement);
                        subElement.className = 'vml';
                        subElement.joinStyle = value
                    }
                if (name === 'opacity' || name === 'strokeOpacity')
                    if (element.stroke)
                        element.stroke.opacity = value >= 0.002 ? value : 0.002;
                    else {
                        subElement = doc.createElement('vml:stroke');
                        vmlElement.element.appendChild(subElement);
                        subElement.className = 'vml';
                        subElement.opacity = value >= 0.002 ? value : 0.002;
                        if (params.strokecolor)
                            subElement.color = params.strokecolor
                    }
                if (name === 'dashstyle')
                    if (element.stroke)
                        element.stroke.dashstyle = value;
                    else {
                        subElement = doc.createElement('vml:stroke');
                        vmlElement.element.appendChild(subElement);
                        subElement.className = 'vml';
                        subElement.dashstyle = value
                    }
            };
        var getBoundingClientRect = function(element) {
                var i,
                    resultRect,
                    rect,
                    tagName = element.tagName.toLowerCase(),
                    points,
                    value,
                    halfStrokeWidth;
                if (tagName === 'div') {
                    if (element.childNodes.length > 0) {
                        resultRect = {};
                        for (i = 0; i < element.childNodes.length; i++) {
                            rect = getBoundingClientRect(element.childNodes[i]);
                            if (!rect)
                                continue;
                            resultRect.left = resultRect.left === undefined || rect.left < resultRect.left ? rect.left : resultRect.left;
                            resultRect.top = resultRect.top === undefined || rect.top < resultRect.top ? rect.top : resultRect.top;
                            resultRect.right = resultRect.right === undefined || rect.right > resultRect.right ? rect.right : resultRect.right;
                            resultRect.bottom = resultRect.bottom === undefined || rect.bottom > resultRect.bottom ? rect.bottom : resultRect.bottom
                        }
                    }
                }
                else if (tagName === 'shape' || tagName === 'vml:shape') {
                    points = (element.path.value || element.path).match(/[-0-9]+/g);
                    resultRect = {};
                    rect = element.getBoundingClientRect();
                    for (i = 0; i < points.length; i++) {
                        value = parseInt(points[i]);
                        if (i % 2) {
                            resultRect.top = resultRect.top === undefined || value < resultRect.top ? value : resultRect.top;
                            resultRect.bottom = resultRect.bottom === undefined || value > resultRect.bottom ? value : resultRect.bottom
                        }
                        else {
                            resultRect.left = resultRect.left === undefined || value < resultRect.left ? value : resultRect.left;
                            resultRect.right = resultRect.right === undefined || value > resultRect.right ? value : resultRect.right
                        }
                    }
                    resultRect.left = resultRect.left || 0;
                    resultRect.top = resultRect.top || 0;
                    resultRect.right = resultRect.right || 0;
                    resultRect.bottom = resultRect.bottom || 0;
                    if (rect.right - rect.left <= 1 && rect.top - rect.bottom <= 1) {
                        resultRect.right = resultRect.right + rect.left;
                        resultRect.bottom = resultRect.bottom + rect.top;
                        resultRect.left = resultRect.left + rect.left;
                        resultRect.top = resultRect.top + rect.top
                    }
                    else {
                        resultRect.right = resultRect.right - resultRect.left + rect.left;
                        resultRect.bottom = resultRect.bottom - resultRect.top + rect.top;
                        resultRect.left = rect.left;
                        resultRect.top = rect.top
                    }
                    halfStrokeWidth = Math.ceil(parseFloat(element.strokeweight) / 2);
                    if (halfStrokeWidth && halfStrokeWidth > 1) {
                        resultRect.left -= halfStrokeWidth;
                        resultRect.top -= halfStrokeWidth;
                        resultRect.right += halfStrokeWidth;
                        resultRect.bottom += halfStrokeWidth
                    }
                }
                else
                    resultRect = element.getBoundingClientRect();
                return resultRect
            };
        var BaseVmlElement = {
                isVml: function() {
                    return true
                },
                dispose: function() {
                    this.childElements = null;
                    this._style = null;
                    this._fullSettings = null;
                    this.callBase()
                },
                defaultSettings: function(customOptions) {
                    return extendDefaultVmlOptions(customOptions, this.callBase ? this.callBase() : {})
                },
                createElement: function(nodeName) {
                    this._nodeName = nodeName;
                    this.childElements = [];
                    this._fullSettings = {};
                    if (this.isVml()) {
                        var result = doc.createElement('vml:' + nodeName);
                        result.className = 'vml';
                        return result
                    }
                    else
                        return doc.createElement(nodeName)
                },
                detach: function() {
                    this.callBase();
                    var parent = this.parentElement,
                        index;
                    this._delayAttributes(['opacity']);
                    if (parent) {
                        index = $.inArray(this, parent.childElements);
                        if (index >= 0)
                            parent.childElements.splice(index, 1);
                        this.parentElement = null
                    }
                },
                clear: function() {
                    this.callBase();
                    this.childElements = []
                },
                applyStyle: function(style) {
                    this.callBase(style);
                    if (style.opacity)
                        this.element.style.opacity = style.opacity
                },
                _fillAttributesFromParentAndCurrentStyle: function(attributes) {
                    var element = this.element,
                        parent = this.parentElement,
                        i,
                        settingToStyleMap = {strokeWidth: 'stroke-width'},
                        propertyName,
                        styleName,
                        settingsToApply = {};
                    if (parent)
                        for (i = 0; i < INHERITABLE_PROPERTIES.length; i++) {
                            propertyName = INHERITABLE_PROPERTIES[i];
                            if (!this.settings[propertyName] && parent._fullSettings[propertyName])
                                settingsToApply[propertyName] = parent._fullSettings[propertyName]
                        }
                    if (element.style && element.currentStyle)
                        for (i = 0; i < INHERITABLE_PROPERTIES.length; i++) {
                            propertyName = INHERITABLE_PROPERTIES[i];
                            styleName = settingToStyleMap[propertyName] || propertyName;
                            if (element.currentStyle[styleName])
                                settingsToApply[propertyName] = element.currentStyle[styleName]
                        }
                    $.extend(this._fullSettings, this.settings, settingsToApply);
                    if (this.isVml())
                        $.extend(attributes, this._normalizeSettings(settingsToApply))
                },
                _applyAttributes: function(params) {
                    var name,
                        value;
                    if (params && params.arcsize !== undefined) {
                        try {
                            this.element.setAttribute('arcsize', params.arcsize)
                        }
                        catch(e) {}
                        this.__appliedSettings = {arcsize: params.arcsize};
                        delete params.arcsize
                    }
                    if (params && params['class']) {
                        this.element.className = (this.isVml() ? 'vml ' : '') + params['class'];
                        delete params['class']
                    }
                    if (!this._isAppended)
                        this._delayedAttributes = params;
                    else {
                        params = params || this._delayedAttributes;
                        if (params) {
                            this._fillAttributesFromParentAndCurrentStyle(params);
                            if (this.isVml())
                                for (name in params) {
                                    value = params[name];
                                    if (name === 'opacity' || name === 'fillOpacity' || name === 'strokeOpacity' || name === 'dashstyle' || name === 'joinStyle')
                                        applySubElementAttribute(this, params, name);
                                    else
                                        this.element[name] = value
                                }
                            this.__appliedSettings = this.isVml() ? params : {};
                            delete this._delayedAttributes
                        }
                    }
                },
                appendComplete: function() {
                    if (this.renderer.isElementAppendedToPage(this)) {
                        this._isAppended = true;
                        this._applyAttributes();
                        $.each(this.childElements, function(_, child) {
                            child.appendComplete()
                        })
                    }
                    else {
                        vmlElementsToAppend.push(this);
                        $(this.element).data('vmlNeedAppendComplete', true);
                        if (appendTimerID === undefined)
                            appendTimerID = setTimeout(function() {
                                appendTimerID = undefined;
                                var vmlElements = vmlElementsToAppend;
                                vmlElementsToAppend = [];
                                $.each(vmlElements, function() {
                                    if ($(this.element).data('vmlNeedAppendComplete') && !this._isAppended)
                                        this.appendComplete()
                                })
                            }, 200)
                    }
                },
                append: function(element) {
                    var self = this,
                        root = self.renderer.getRoot(),
                        toElement = element || root;
                    if (toElement) {
                        toElement.element.appendChild(self.element);
                        toElement.childElements.push(self);
                        self.parentElement = toElement
                    }
                    if (toElement === root || toElement._isAppended)
                        this.appendComplete();
                    return self
                },
                insertBefore: function(target) {
                    var parent = target.parentElement;
                    parent.element.insertBefore(this.element, target.element);
                    this.parentElement = parent;
                    parent.childElements.splice($.inArray(target, parent.childElements), 0, this);
                    parent._isAppended && this.appendComplete();
                    return this
                },
                _delayAttributes: function(attributes) {
                    var attr,
                        val,
                        i,
                        settings = this.settings || {};
                    attributes = attributes || [];
                    this._delayedAttributes = this._delayedAttributes || {};
                    for (i = 0; i < attributes.length; i++) {
                        attr = attributes[i];
                        val = settings[attr];
                        if (val)
                            this._delayedAttributes[attr] = val
                    }
                    $.each(this.childElements || [], function(_, child) {
                        child._delayAttributes(attributes)
                    })
                },
                _normalizeSettings: function(settings) {
                    var key,
                        style = {},
                        normalized = {},
                        clipRect,
                        pos,
                        prop,
                        value;
                    for (key in settings) {
                        prop = key;
                        value = settings[prop];
                        if (prop === 'x' || prop === 'translateX') {
                            pos = settings.x || 0;
                            if (settings.translateX)
                                pos += settings.translateX;
                            style.left = pos + 'px'
                        }
                        else if (prop === 'y' || prop === 'translateY') {
                            pos = settings.y || 0;
                            if (settings.translateY)
                                pos += settings.translateY;
                            style.top = pos + 'px'
                        }
                        else if (prop === 'width')
                            style.width = value + 'px';
                        else if (prop === 'height')
                            style.height = value + 'px';
                        else if (prop === 'align')
                            continue;
                        else if (prop === 'scale')
                            continue;
                        else if ($.inArray(prop, CSS_PROPERTIES) != -1)
                            style[prop] = value;
                        else if (prop === 'font') {
                            if (!$.isPlainObject(value))
                                continue;
                            $.each(value, function(fontSetting) {
                                var styleName,
                                    firstChar;
                                switch (fontSetting) {
                                    case'color':
                                    case'opacity':
                                        break;
                                    case'cursor':
                                        styleName = fontSetting;
                                        break;
                                    default:
                                        firstChar = fontSetting.charAt(0);
                                        styleName = 'font' + fontSetting.replace(firstChar, firstChar.toUpperCase())
                                }
                                if (styleName)
                                    style[styleName] = value[fontSetting]
                            })
                        }
                        else if (prop === 'style')
                            $.extend(true, style, value);
                        else if (prop === 'rotate')
                            this['_rotate'] = value;
                        else if (prop === 'clipId') {
                            clipRect = this.renderer.getClipRect(value, this);
                            if (clipRect) {
                                var width = clipRect.width,
                                    height = clipRect.height,
                                    x = clipRect.x,
                                    y = clipRect.y,
                                    clipWidth = width + x,
                                    clipHeight = height + y;
                                style.width = clipRect.cSize.width;
                                style.height = clipRect.cSize.height;
                                style.clip = "rect(" + y + "px, " + clipWidth + "px, " + clipHeight + "px, " + x + "px)"
                            }
                        }
                        else if (prop === 'segments')
                            continue;
                        else if (prop === 'fill') {
                            normalized.filled = value === 'none' ? 'f' : 't';
                            normalized.fillcolor = value === 'grey' ? '#808080' : value
                        }
                        else if (prop === 'opacity')
                            normalized.opacity = value < 0.002 ? value : value;
                        else if (prop === 'stroke') {
                            normalized.stroked = value === 'none' ? 'f' : 't';
                            normalized.strokecolor = value
                        }
                        else if (prop === 'strokeWidth')
                            normalized.strokeweight = value + 'px';
                        else if (prop === 'lineJoin')
                            normalized.joinStyle = value;
                        else if (prop === 'dashStyle') {
                            value = value.toLowerCase();
                            if (value !== 'solid')
                                normalized.dashstyle = value
                        }
                        else
                            normalized[prop] = value
                    }
                    this['_style'] = style;
                    return normalized
                },
                _getBBox: function() {
                    var width,
                        height,
                        rect,
                        parentRect,
                        x = 0,
                        y = 0,
                        element = this.element,
                        parent;
                    try {
                        rect = getBoundingClientRect(element);
                        width = rect.right - rect.left;
                        height = rect.bottom - rect.top;
                        parent = this.element.parentNode || this.renderer.getRoot().element;
                        parentRect = parent.getBoundingClientRect();
                        x = rect.left - parentRect.left;
                        y = rect.top - parentRect.top;
                        if (element.tagName.toLowerCase() === 'div') {
                            x = x - (parseInt(element.style.left, 10) || 0);
                            y = y - (parseInt(element.style.top, 10) || 0)
                        }
                    }
                    catch(e) {
                        width = element.offsetWidth || 0;
                        height = element.offsetHeight || 0
                    }
                    return {
                            x: x,
                            y: y,
                            width: width,
                            height: height,
                            isEmpty: !x && !y && !width && !height
                        }
                },
                getBBox: function() {
                    return this._getBBox()
                },
                sharpEdges: function(){}
            };
        var convertSvgPathCommandToVml = function(command) {
                switch (command) {
                    case'M':
                        return 'm';
                    case'L':
                        return 'l';
                    case'Z':
                        return 'x e'
                }
                return command
            };
        var BasePathVmlElement = {
                defaultSettings: function() {
                    return $.extend(this.callBase(), {coordsize: '1,1'})
                },
                getNodeName: function() {
                    return 'shape'
                },
                getPathAttributeName: function() {
                    return 'path'
                },
                customizeSegments: function(segments) {
                    var result = segments;
                    if (segments)
                        result = $.map(segments, function(s, i) {
                            var pos,
                                segmentArray = [],
                                command = convertSvgPathCommandToVml(s[0]);
                            segmentArray.push(command);
                            for (pos = 1; pos < s.length; pos++)
                                segmentArray.push(Math.floor(s[pos]));
                            return [segmentArray]
                        });
                    return result
                }
            };
        var RootVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({
                isVml: function() {
                    return false
                },
                defaultSettings: function() {
                    return {
                            width: 0,
                            height: 0,
                            position: 'relative',
                            display: 'inline-block',
                            overflow: 'hidden',
                            stroke: 'none',
                            strokeWidth: 0,
                            fill: 'none'
                        }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'div', params)
                }
            });
        var ImageVmlElement = svgRendererInternals.BaseSvgElement.inherit(svgRendererInternals.RectSvgBaseElement).inherit(BaseVmlElement).inherit({
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'image', params)
                },
                defaultSettings: function() {
                    return $.extend(this.callBase(), {strokeWidth: 0})
                },
                adjustSettings: function() {
                    this.callBase();
                    if (this.settings.href) {
                        this.settings.src = this.settings.href;
                        delete this.settings.href
                    }
                }
            });
        var RectVmlElement = svgRendererInternals.BaseSvgElement.inherit(svgRendererInternals.RectSvgBaseElement).inherit(BaseVmlElement).inherit({
                defaultSettings: function() {
                    return extendDefaultVmlOptions({
                            stroked: 'f',
                            strokeWidth: 0,
                            rx: 0,
                            ry: 0
                        })
                },
                recreateElement: function(name) {
                    this._nodeName = name;
                    var parent = this.$element.parent()[0];
                    if (parent) {
                        var $oldElement = this.$element;
                        this.element = this.createElement(name);
                        this.$element = $(this.element);
                        this.$element.insertBefore($oldElement);
                        $oldElement.remove()
                    }
                    else {
                        this.element = this.createElement(name);
                        this.$element = $(this.element)
                    }
                    this.applySettings()
                },
                _adjustArcSize: function() {
                    var settings = this.settings;
                    var rx = settings.rx || 0,
                        ry = settings.ry || 0,
                        width = settings.width,
                        height = settings.height,
                        r,
                        halfsize,
                        arcsize;
                    if (settings.rx !== undefined || settings.ry !== undefined) {
                        r = Math.max(rx, ry);
                        halfsize = Math.max(width, height) / 2;
                        arcsize = r / halfsize;
                        settings.arcsize = arcsize;
                        if ($.isNumeric(arcsize) && arcsize != 0)
                            this._nodeName !== 'roundrect' && this.recreateElement('roundrect');
                        else
                            this._nodeName === 'roundrect' && this.recreateElement('rect');
                        delete settings.rx;
                        delete settings.ry
                    }
                },
                _adjustRotation: function() {
                    var settings = this.settings;
                    var rotate = this.settings.rotate,
                        rotateAngle,
                        radianAngle,
                        cos,
                        sin,
                        rotateX,
                        rotateY,
                        marginTop,
                        marginLeft,
                        cx,
                        cy,
                        rotateObject;
                    rotateObject = parseRotateParameter(rotate, settings.x, settings.y);
                    if (rotateObject) {
                        rotateAngle = rotateObject.angle;
                        rotateX = rotateObject.x;
                        rotateY = rotateObject.y;
                        radianAngle = rotateAngle * Math.PI / 180.0;
                        cos = Math.cos(radianAngle);
                        sin = Math.sin(radianAngle);
                        cx = settings.x + (settings.translateX || 0) + settings.width / 2;
                        cy = settings.y + (settings.translateY || 0) + settings.height / 2;
                        marginLeft = (cx - rotateX) * cos - (cy - rotateY) * sin + rotateX - cx;
                        marginTop = (cx - rotateX) * sin + (cy - rotateY) * cos + rotateY - cy;
                        this.settings.marginLeft = Math.round(marginLeft) + 'px';
                        this.settings.marginTop = Math.round(marginTop) + 'px';
                        this.settings.rotation = rotateAngle
                    }
                },
                adjustSettings: function() {
                    this.callBase();
                    this._adjustArcSize();
                    this._adjustRotation()
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'rect', params)
                }
            });
        var PathVmlElement = svgRendererInternals.PathSvgElement.inherit(BaseVmlElement).inherit(BasePathVmlElement).inherit({prepareSegments: function(settings) {
                    var self = this,
                        rotate = settings.rotate,
                        rotateAngle,
                        rotateX,
                        rotateY,
                        oldSegments,
                        radianAngle,
                        cos,
                        sin,
                        x,
                        y,
                        rotatedX,
                        rotatedY,
                        rotateObject;
                    this.callBase(settings);
                    oldSegments = self.segments;
                    rotateObject = parseRotateParameter(rotate, settings.x, settings.y);
                    if (rotateObject) {
                        rotateAngle = rotateObject.angle;
                        rotateX = rotateObject.x;
                        rotateY = rotateObject.y;
                        if (self.segments) {
                            radianAngle = rotateAngle * Math.PI / 180.0;
                            cos = Math.cos(radianAngle);
                            sin = Math.sin(radianAngle);
                            self.segments = $.map(self.segments, function(s, i) {
                                if (s.length === 3) {
                                    x = s[1],
                                    y = s[2];
                                    rotatedX = (x - rotateX) * cos - (y - rotateY) * sin + rotateX;
                                    rotatedY = (x - rotateX) * sin + (y - rotateY) * cos + rotateY;
                                    return [[s[0], Math.floor(rotatedX), Math.floor(rotatedY)]]
                                }
                                else
                                    return [s]
                            });
                            self.combinePathParams(settings);
                            self.segments = oldSegments
                        }
                    }
                }});
        var SimplePathVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({
                ctor: function(renderer, options) {
                    this.callBase(renderer, 'shape', options)
                },
                defaultSettings: function() {
                    return extendDefaultVmlOptions({coordsize: '1,1'})
                },
                adjustSettings: function() {
                    var settings = this.settings;
                    if (settings.d !== undefined) {
                        settings.path = settings.d;
                        delete settings.d
                    }
                }
            });
        var AreaVmlElement = PathVmlElement.inherit({
                defaultSettings: function() {
                    var baseOptions = this.callBase();
                    return extendDefaultVmlOptions({points: {
                                x: 0,
                                y: 0
                            }}, baseOptions)
                },
                ctor: function(renderer, params) {
                    this.closePath = true;
                    this.callBase(renderer, params)
                }
            });
        var SegmentRectVmlElement = svgRendererInternals.SegmentRectSvgElement.inherit(BaseVmlElement).inherit(BasePathVmlElement).inherit({
                defaultSettings: function() {
                    var settings = this.callBase();
                    settings.lineJoin = 'miter';
                    delete settings.fill;
                    delete settings.stroke;
                    delete settings.strokecolor;
                    delete settings.stroked;
                    return settings
                },
                prepareSegments: function() {
                    this.callBase();
                    this.segments = this.customizeSegments(this.segments);
                    this.settings.x = 0;
                    this.settings.y = 0;
                    this.settings.width = 1;
                    this.settings.height = 1
                },
                applySettings: function(settings) {
                    var x = settings.x,
                        y = settings.y,
                        w = settings.width,
                        h = settings.height;
                    this.callBase(settings);
                    this.settings.x = x;
                    this.settings.y = y;
                    this.settings.width = w;
                    this.settings.height = h
                }
            });
        var BezierVmlElement = svgRendererInternals.BezierSvgElement.inherit(BaseVmlElement).inherit(BasePathVmlElement);
        var BezierAreaVmlElement = BezierVmlElement.inherit({
                defaultSettings: function() {
                    var baseOptions = this.callBase();
                    return extendDefaultVmlOptions({points: {
                                x: 0,
                                y: 0
                            }}, baseOptions)
                },
                ctor: function(renderer, params) {
                    this.closePath = true;
                    this.callBase(renderer, params)
                }
            });
        var ArcVmlElement = svgRendererInternals.ArcSvgElement.inherit(BaseVmlElement).inherit(BasePathVmlElement).inherit({createArcSegments: function(x, y, innerR, outerR, startAngle, endAngle, isCircle) {
                    var xOuterStart = x + outerR * Math.cos(startAngle),
                        yOuterStart = y - outerR * Math.sin(startAngle),
                        xOuterEnd = x + outerR * Math.cos(endAngle),
                        yOuterEnd = y - outerR * Math.sin(endAngle),
                        xInnerStart = x + innerR * Math.cos(endAngle),
                        yInnerStart = y - innerR * Math.sin(endAngle),
                        xInnerEnd = x + innerR * Math.cos(startAngle),
                        yInnerEnd = y - innerR * Math.sin(startAngle);
                    return [['wr', x - innerR, y - innerR, x + innerR, y + innerR, xInnerStart, yInnerStart, xInnerEnd, yInnerEnd], [isCircle ? 'wr' : 'at', x - outerR, y - outerR, x + outerR, y + outerR, xOuterStart, yOuterStart, xOuterEnd, yOuterEnd], ['x e']]
                }});
        var CircleVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({
                defaultSettings: function() {
                    return extendDefaultVmlOptions({
                            cx: 0,
                            cy: 0,
                            r: 0
                        })
                },
                applySettings: function(settings) {
                    settings.cx = settings.cx || settings.x;
                    settings.cy = settings.cy || settings.y;
                    return this.callBase(settings)
                },
                adjustSettings: function() {
                    var r,
                        cx,
                        cy;
                    if (this.settings.cx !== undefined || this.settings.cy !== undefined || this.settings.r !== undefined) {
                        r = 'r' in this.settings ? this.settings.r : this.settings.width / 2;
                        cx = 'cx' in this.settings ? this.settings.cx : this.settings.x + this.settings.width / 2;
                        cy = 'cy' in this.settings ? this.settings.cy : this.settings.y + this.settings.width / 2;
                        this.settings.x = cx - r;
                        this.settings.y = cy - r;
                        this.settings.width = this.settings.height = r * 2;
                        delete this.settings.cx;
                        delete this.settings.cy;
                        delete this.settings.r
                    }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'oval', params)
                }
            });
        var TextVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({
                isVml: function() {
                    return false
                },
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0,
                            position: 'absolute',
                            whiteSpace: 'nowrap'
                        }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'span', params)
                },
                adjustSettings: function() {
                    var text,
                        settings = this.settings;
                    if (settings.font) {
                        settings.fill = settings.fill || settings.font.color;
                        settings.opacity = settings.opacity || settings.font.opacity
                    }
                    if ('text' in settings) {
                        text = utils.isDefined(settings.text) ? settings.text : '';
                        text = text.toString().replace(/\r/g, "");
                        text = text.replace(/\n/g, "<br/>");
                        $(this.element).html(text);
                        delete settings.text
                    }
                },
                updateText: function(text) {
                    this.applySettings({text: utils.isDefined(text) ? text : ''})
                },
                _applyAttributes: function(settings) {
                    this.callBase(settings);
                    settings = this._fullSettings;
                    var rotate = settings.rotate,
                        rotateAngle = 0,
                        rotateX,
                        rotateY,
                        cos = 1,
                        sin = 0,
                        osin = 0,
                        ocos = 1,
                        angle,
                        otg,
                        rad,
                        y = settings.y + (settings.translateY || 0),
                        x = settings.x + (settings.translateX || 0),
                        align = settings.align,
                        bBox = this.getBBox(),
                        style = this._style || {},
                        marginLeft = 0,
                        marginTop = 0,
                        fontHeightOffset,
                        alignMultiplier,
                        rotateObject,
                        textWidth,
                        textHeight;
                    if (this._oldRotate && !bBox.isEmpty) {
                        rad = this._oldRotate.angle * Math.PI / 180.0;
                        osin = Math.sin(rad);
                        ocos = Math.cos(rad);
                        if ((this._oldRotate.angle | 0) % 90 !== 0)
                            if ((this._oldRotate.angle | 0) % 45 === 0)
                                textWidth = bBox.width,
                                textHeight = bBox.height;
                            else {
                                otg = Math.abs(Math.tan(rad));
                                var b = (bBox.width - bBox.height * otg) / (1 - otg * otg);
                                var a = bBox.width - b;
                                textHeight = Math.abs(a / osin);
                                textWidth = Math.abs(b / ocos)
                            }
                        else {
                            textHeight = Math.abs(bBox.height * ocos - bBox.width * osin);
                            textWidth = Math.abs(bBox.width * ocos - bBox.height * osin)
                        }
                    }
                    else
                        textWidth = bBox.width,
                        textHeight = bBox.height;
                    this.__textWidth = textWidth;
                    this.__textHeight = textHeight;
                    if (textHeight || textWidth) {
                        rotateObject = parseRotateParameter(rotate, x, y);
                        this._oldRotate = rotateObject;
                        if (rotateObject) {
                            rotateAngle = rotateObject.angle;
                            rotateX = rotateObject.x;
                            rotateY = rotateObject.y;
                            if (Math.abs(rotateAngle) > 360)
                                rotateAngle = rotateAngle % 360;
                            if (rotateAngle < 0)
                                rotateAngle = rotateAngle + 360;
                            if (rotateAngle) {
                                rad = rotateAngle * Math.PI / 180.0;
                                cos = Math.cos(rad);
                                sin = Math.sin(rad);
                                style.filter = 'progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand", M11 = ' + cos.toFixed(5) + ', M12 = ' + (-sin).toFixed(5) + ', M21 = ' + sin.toFixed(5) + ', M22 = ' + cos.toFixed(5) + ')'
                            }
                            else {
                                style.filter = '';
                                this._oldRotate = null
                            }
                            marginLeft = (x - rotateX) * (cos - 1) - (y - rotateY) * sin;
                            marginTop = (x - rotateX) * sin + (y - rotateY) * (cos - 1)
                        }
                        fontHeightOffset = textHeight * (0.55 + 0.45 / 2);
                        if (rotateAngle < 90) {
                            marginTop -= fontHeightOffset * cos;
                            marginLeft -= (textHeight - fontHeightOffset) * sin
                        }
                        else if (rotateAngle < 180) {
                            marginTop += (textHeight - fontHeightOffset) * cos;
                            marginLeft += textWidth * cos - (textHeight - fontHeightOffset) * sin
                        }
                        else if (rotateAngle < 270) {
                            marginTop += (textHeight - fontHeightOffset) * cos + textWidth * sin;
                            marginLeft += textWidth * cos + fontHeightOffset * sin
                        }
                        else {
                            marginTop += textWidth * sin - fontHeightOffset * cos;
                            marginLeft += fontHeightOffset * sin
                        }
                        alignMultiplier = {
                            center: 0.5,
                            right: 1
                        }[align];
                        if (alignMultiplier) {
                            marginLeft -= textWidth * alignMultiplier * cos;
                            marginTop -= textWidth * alignMultiplier * sin
                        }
                        style.marginLeft = Math.round(marginLeft) + 'px';
                        style.marginTop = Math.round(marginTop) + 'px'
                    }
                    if (settings.fill && settings.fill !== 'none')
                        style.color = settings.fill;
                    if (settings.opacity)
                        this.element.style.filter = 'alpha(opacity=' + settings.opacity * 100 + ')';
                    this.applyStyle(style)
                }
            });
        var GroupVmlElement = svgRendererInternals.BaseSvgElement.inherit(BaseVmlElement).inherit({
                isVml: function() {
                    return false
                },
                defaultSettings: function() {
                    return {
                            x: 0,
                            y: 0,
                            position: 'absolute'
                        }
                },
                ctor: function(renderer, params) {
                    this.callBase(renderer, 'div', params)
                },
                applySettings: function(settings) {
                    var callBase = this.callBase,
                        rotate;
                    settings = settings || {};
                    rotate = settings.rotate;
                    if (rotate) {
                        if (utils.isNumber(rotate))
                            rotate = [rotate, settings.x || 0, settings.y || 0];
                        $.each(this.childElements, function(_, child) {
                            child.applySettings({rotate: rotate})
                        })
                    }
                    delete settings.rotate;
                    delete settings.x;
                    delete settings.y;
                    this.callBase = callBase;
                    return this.callBase(settings)
                },
                getBBox: function() {
                    return this._getBBox()
                },
                update: function() {
                    if (this.settings.clipId) {
                        var bbox = this.getBBox();
                        this.applyStyle({
                            left: bbox.x + (this.settings.translateX || 0),
                            right: bbox.y + (this.settings.translateY || 0),
                            width: bbox.width,
                            height: bbox.height
                        })
                    }
                }
            });
        renderers.VmlRenderer = renderers.SvgRenderer.inherit({
            ctor: function(options) {
                options = options || {};
                options.animation = {enabled: false};
                if (document.namespaces && !document.namespaces.vml) {
                    document.namespaces.add('vml', 'urn:schemas-microsoft-com:vml');
                    document.createStyleSheet().addRule('.vml', 'behavior: url(#default#VML); display: inline-block;')
                }
                this._clipRects = {};
                this.cssClass = options.cssClass || '';
                this.callBase(options)
            },
            dispose: function() {
                this.callBase();
                this._clipRects = null;
                this._size = null
            },
            updateAnimationOptions: $.noop,
            draw: function(container) {
                var root = this.getRoot();
                this.callBase(container);
                if (root)
                    root.appendComplete()
            },
            recreateCanvas: function(width, height, cssClass) {
                if (width > 0 && height > 0) {
                    this._size = {
                        width: width,
                        height: height
                    };
                    if (!this.svgRoot) {
                        this.cssClass = cssClass || this.cssClass;
                        this.svgRoot = new RootVmlElement(this, {
                            width: width,
                            height: height,
                            'class': this.cssClass
                        })
                    }
                    else
                        this.svgRoot.applySettings({
                            width: width,
                            height: height
                        });
                    this.defsSvg && this.defsSvg.clear()
                }
            },
            _getSize: function() {
                return this._size || {}
            },
            isElementAppendedToPage: function(element) {
                return $(element.element).closest(document.documentElement).length
            },
            createRect: function(x, y, w, h, r, options) {
                var params = $.extend(true, {}, options || {}, {
                        x: x,
                        y: y,
                        width: w,
                        height: h,
                        rx: r,
                        ry: r
                    });
                return new RectVmlElement(this, params)
            },
            createSegmentRect: function(x, y, w, h, r, segments, options) {
                var params = $.extend({}, options || {}, {
                        x: x,
                        y: y,
                        width: w,
                        height: h,
                        rx: r,
                        ry: r,
                        segments: segments
                    });
                return new SegmentRectVmlElement(this, params)
            },
            createClipRect: function(x, y, width, height) {
                var clipId = utils.getNextClipId(),
                    elements = [],
                    clipRect = {
                        id: clipId,
                        x: x,
                        y: y,
                        width: width,
                        height: height,
                        cSize: this._getSize(),
                        addElement: function(element) {
                            var hasElement = false;
                            $.each(elements, function() {
                                if (this === element) {
                                    hasElement = true;
                                    return false
                                }
                            });
                            if (!hasElement)
                                elements.push(element)
                        },
                        append: function() {
                            return this
                        },
                        remove: function(){},
                        dispose: function(){},
                        updateRectangle: function(settings) {
                            if ('x' in settings)
                                this.x = settings.x;
                            if ('translateX' in settings)
                                this.x += settings.translateX;
                            if ('y' in settings)
                                this.y = settings.y;
                            if ('translateY' in settings)
                                this.y += settings.translateY;
                            if ('width' in settings)
                                this.width = settings.width;
                            if ('height' in settings)
                                this.height = settings.height;
                            $.each(elements, function() {
                                this.applySettings({clipId: clipId})
                            });
                            return this
                        }
                    };
                this._clipRects[clipId] = clipRect;
                return clipRect
            },
            getClipRect: function(clipId, element) {
                var clipRect = this._clipRects[clipId];
                if (clipRect && element)
                    clipRect.addElement(element);
                return this._clipRects[clipId]
            },
            createImage: function(x, y, w, h, href, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {
                        x: x,
                        y: y,
                        width: w,
                        height: h,
                        href: href
                    });
                return new ImageVmlElement(this, params)
            },
            createLine: function(x1, y1, x2, y2, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: [x1, y1, x2, y2]});
                return new PathVmlElement(this, params)
            },
            createPath: function(points, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: points});
                return new PathVmlElement(this, params)
            },
            createSimplePath: function(options) {
                return new SimplePathVmlElement(this, options)
            },
            createBezierPath: function(points, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: points});
                return new BezierVmlElement(this, params)
            },
            createArea: function(points, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: points});
                return new AreaVmlElement(this, params)
            },
            createBezierArea: function(points, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {points: points});
                return new BezierAreaVmlElement(this, params)
            },
            createCircle: function(x, y, r, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {
                        cx: x,
                        cy: y,
                        r: r
                    });
                return new CircleVmlElement(this, params)
            },
            createArc: function(x, y, outerRadius, innerRadius, startAngle, endAngle, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {
                        x: x,
                        y: y,
                        outerRadius: outerRadius,
                        innerRadius: innerRadius,
                        startAngle: startAngle,
                        endAngle: endAngle
                    });
                return new ArcVmlElement(this, params)
            },
            createText: function(text, x, y, options) {
                var params = $.extend(true, {}, options && !options.inh ? options : {}, {
                        x: x,
                        y: y,
                        text: text
                    });
                return new TextVmlElement(this, params)
            },
            createGroup: function(options) {
                return new GroupVmlElement(this, options)
            },
            createPattern: function(color, hatching) {
                return {
                        id: color,
                        append: function() {
                            return this
                        },
                        clear: function(){},
                        dispose: function(){}
                    }
            },
            createFilter: function(type) {
                if (type === 'shadow')
                    return {
                            ref: null,
                            append: function() {
                                return this
                            },
                            dispose: function() {
                                return this
                            },
                            applySettings: function() {
                                return this
                            }
                        };
                return null
            }
        });
        function buildPath(points) {
            var i = 0,
                ii = points.length,
                list = [];
            for (; i < ii; )
                list.push('l', points[i++].toFixed(0), points[i++].toFixed(0));
            if (ii) {
                list[0] = 'm';
                list.push('x e');
                list = list.join(' ')
            }
            else
                list = '';
            return list
        }
        renderers._vmlBuildPath = buildPath;
        renderers.__vmlRendererInternals = {
            RootVmlElement: RootVmlElement,
            RectVmlElement: RectVmlElement,
            ImageVmlElement: ImageVmlElement,
            PathVmlElement: PathVmlElement,
            AreaVmlElement: AreaVmlElement,
            BezierVmlElement: BezierVmlElement,
            BezierAreaVmlElement: BezierAreaVmlElement,
            SimplePathVmlElement: SimplePathVmlElement,
            CircleVmlElement: CircleVmlElement,
            TextVmlElement: TextVmlElement,
            GroupVmlElement: GroupVmlElement,
            ArcVmlElement: ArcVmlElement,
            SegmentRectVmlElement: SegmentRectVmlElement
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file renderer.js */
    (function($, DX) {
        function supportSVG() {
            return !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', "svg").createSVGRect
        }
        var renderers = DX.viz.renderers,
            browser = DX.browser;
        if (browser.msie && browser.version < 9 && !supportSVG()) {
            renderers.Renderer = renderers.VmlRenderer;
            renderers.buildPath = renderers._vmlBuildPath
        }
        else {
            renderers.Renderer = renderers.SvgRenderer;
            renderers.buildPath = renderers._svgBuildPath
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file animation.js */
    (function(DX) {
        var renderers = DX.viz.renderers,
            Class = DX.Class,
            easingFunctions,
            noop = function(){};
        easingFunctions = {
            easeOutCubic: function(pos, start, end) {
                return pos === 1 ? end : (1 - Math.pow(1 - pos, 3)) * (end - start) + +start
            },
            linear: function(pos, start, end) {
                return pos === 1 ? end : pos * (end - start) + +start
            }
        };
        renderers.easingFunctions = easingFunctions;
        renderers.animationSvgStep = {
            points: function(elem, params, progress, easing, currentParams) {
                var from = params.from,
                    to = params.to,
                    path = [],
                    i,
                    j,
                    seg;
                for (i = 0; i < from.length; i++) {
                    seg = [from[i][0]];
                    if (from[i].length > 1)
                        for (j = 1; j < from[i].length; j++)
                            seg.push(easing(progress, from[i][j], to[i][j]));
                    path[i] = seg.join(' ')
                }
                currentParams.d = path.join(' ');
                elem.element.setAttribute('d', currentParams.d)
            },
            transform: function(elem, params, progress, easing, currentParams) {
                var translate = params.translate,
                    rotate = params.rotate,
                    scale = params.scale,
                    transformations = [],
                    elemSettings = elem.settings;
                if (translate) {
                    currentParams.translateX = easing(progress, translate.x.from, translate.x.to);
                    currentParams.translateY = easing(progress, translate.y.from, translate.y.to);
                    transformations.push('translate(' + currentParams.translateX + ',' + currentParams.translateY + ')')
                }
                else if (elemSettings.translateX || elemSettings.translateY)
                    transformations.push('translate(' + (elemSettings.translateX || 0) + ',' + (elemSettings.translateY || 0) + ')');
                if (rotate) {
                    currentParams.rotate = {
                        rotateAngle: easing(progress, rotate.angle.from, rotate.angle.to),
                        rotateX: rotate.x,
                        rotateY: rotate.y
                    };
                    transformations.push('rotate(' + currentParams.rotate.rotateAngle + ',' + rotate.x + ',' + rotate.y + ')')
                }
                else if (elemSettings.rotate)
                    transformations.push('rotate(' + elemSettings.rotate.angle + ',' + (elemSettings.rotate.x || 0) + ',' + (elemSettings.rotate.y || 0) + ')');
                if (scale) {
                    currentParams.scale = {
                        x: easing(progress, scale.x.from, scale.x.to),
                        y: easing(progress, scale.y.from, scale.y.to)
                    };
                    transformations.push('scale(' + currentParams.scale.x + ',' + currentParams.scale.y + ')')
                }
                else if (elemSettings.scale)
                    transformations.push('scale(' + elemSettings.scale.x + ',' + elemSettings.scale.y + ')');
                elem.element.setAttribute('transform', transformations.join())
            },
            base: function(elem, params, progress, easing, currentParams, attributeName) {
                currentParams[attributeName] = easing(progress, params.from, params.to);
                elem.element.setAttribute(attributeName, currentParams[attributeName])
            },
            _: noop,
            complete: function(element, currentSettings) {
                element.applySettings(currentSettings)
            }
        };
        var Animation = Class.inherit({
                ctor: function(element, params, options) {
                    var _this = this;
                    _this._progress = 0;
                    _this.element = element;
                    _this.params = params;
                    _this.options = options;
                    _this.duration = options.partitionDuration ? options.duration * options.partitionDuration : options.duration;
                    _this._animateStep = options.animateStep || renderers.animationSvgStep;
                    _this._easing = easingFunctions[options.easing || 'easeOutCubic'];
                    _this._currentParams = {};
                    _this.tick = _this._start
                },
                _calcProgress: function(now) {
                    return Math.min(1, (now - this._startTime) / this.duration)
                },
                _step: function(now) {
                    var _this = this,
                        animateStep = _this._animateStep,
                        attrName;
                    _this._progress = _this._calcProgress(now);
                    for (attrName in _this.params) {
                        if (!_this.params.hasOwnProperty(attrName))
                            continue;
                        var anim = animateStep[attrName] || animateStep.base;
                        anim(_this.element, _this.params[attrName], _this._progress, _this._easing, _this._currentParams, attrName)
                    }
                    _this.options.step && _this.options.step(_this._easing(_this._progress, 0, 1), _this._progress);
                    if (_this._progress === 1)
                        return _this.stop();
                    return true
                },
                _start: function(now) {
                    this._startTime = now;
                    this.tick = this._step;
                    return true
                },
                _end: function() {
                    var _this = this;
                    _this.stop = noop;
                    _this.tick = noop;
                    _this.options.complete && _this.options.complete();
                    _this._animateStep.complete && _this._animateStep.complete(_this.element, _this._currentParams)
                },
                tick: function(now) {
                    return true
                },
                stop: function(breakAnimation) {
                    var options = this.options;
                    if (!breakAnimation && options.repeatCount && --options.repeatCount > 0) {
                        this.tick = this._start;
                        return true
                    }
                    else
                        this._end()
                }
            });
        renderers.AnimationController = Class.inherit(function() {
            var FPS = 1000 / 60,
                requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
                    setTimeout(callback, FPS)
                };
            return {
                    ctor: function() {
                        var _this = this;
                        _this.requestAnimationFrame = requestAnimationFrame;
                        _this._animationCount = 0;
                        _this._timerId = null;
                        _this._animations = {}
                    },
                    _loop: function() {
                        var _this = this,
                            animations = _this._animations,
                            activeAnimation = 0,
                            now = (new Date).getTime(),
                            an;
                        for (an in animations) {
                            if (!animations.hasOwnProperty(an))
                                continue;
                            if (!animations[an].tick(now))
                                delete animations[an];
                            activeAnimation++
                        }
                        if (activeAnimation === 0) {
                            _this.stop();
                            return
                        }
                        _this._timerId = _this.requestAnimationFrame.call(null, function() {
                            _this._loop()
                        }, _this.element)
                    },
                    addAnimation: function(animation) {
                        var _this = this;
                        _this._animations[_this._animationCount++] = animation;
                        if (!_this._timerId) {
                            clearTimeout(_this._startDelay);
                            _this._startDelay = setTimeout(function() {
                                _this._timerId = 1;
                                _this._loop()
                            }, 0)
                        }
                    },
                    animateElement: function(elem, params, options) {
                        if (elem && params && options) {
                            elem.animation && elem.animation.stop(true);
                            this.addAnimation(elem.animation = new Animation(elem, params, options))
                        }
                    },
                    dispose: function() {
                        this.stop();
                        this.element = null
                    },
                    stop: function() {
                        this._animations = {};
                        this._animationCount = 0;
                        clearTimeout(this._startDelay);
                        this._timerId = null
                    }
                }
        }());
        renderers.Animation = Animation;
        renderers.noop = noop
    })(DevExpress);
    /*! Module viz-core, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz.charts = {series: {}}
    })(DevExpress);
    /*! Module viz-core, file range.js */
    (function($, DX, undefined) {
        var isDefinedUtils = DX.utils.isDefined,
            isDateUtils = DX.utils.isDate,
            utils = DX.utils;
        var NUMBER_EQUALITY_CORRECTION = 1,
            DATETIME_EQUALITY_CORRECTION = 60000;
        DX.viz.charts.Range = DX.Class.inherit(function() {
            var ctor = function(range) {
                    range && $.extend(this, range)
                };
            var dispose = function() {
                    this.categoriesY = null;
                    this.categoriesX = null
                };
            var otherLessThan = function(thisValue, otherValue) {
                    return otherValue < thisValue
                };
            var otherGreaterThan = function(thisValue, otherValue) {
                    return otherValue > thisValue
                };
            var compareAndReplace = function(thisValue, otherValue, setValue, compare) {
                    var thisValueDefined = thisValue !== undefined,
                        otherValueDefined = otherValue !== undefined;
                    if (thisValueDefined) {
                        if (otherValueDefined && compare(thisValue, otherValue))
                            setValue(otherValue)
                    }
                    else if (otherValueDefined)
                        setValue(otherValue)
                };
            var getBoundRange = function(otherRange) {
                    getBoundRangeX.call(this, otherRange);
                    getBoundRangeY.call(this, otherRange);
                    return this
                };
            var getBoundRangeY = function(otherRange) {
                    var self = this,
                        categoriesY = self.categoriesY,
                        otherCategoriesY = otherRange.categoriesY,
                        i;
                    var setIndentByPriority = function(prefix) {
                            var priorityRelation = (self[prefix + 'Priority'] || 0) - (otherRange[prefix + 'Priority'] || 0);
                            if ((self[prefix] || 0) < otherRange[prefix] && priorityRelation === 0 || priorityRelation < 0) {
                                self[prefix] = otherRange[prefix];
                                self[prefix + 'Priority'] = otherRange[prefix + 'Priority']
                            }
                        };
                    self.invertY = self.invertY || otherRange.invertY;
                    self.stickY = self.stickY || otherRange.stickY;
                    self.axisTypeY = self.axisTypeY || otherRange.axisTypeY;
                    if (self.axisTypeY === 'logarithmic')
                        self.baseY = self.baseY || otherRange.baseY;
                    else
                        self.baseY = undefined;
                    self.keepValueMarginsY = self.keepValueMarginsY || otherRange.keepValueMarginsY;
                    compareAndReplace(self.minY, otherRange.minY, function(value) {
                        self.minY = value
                    }, otherLessThan);
                    compareAndReplace(self.intervalY, otherRange.intervalY, function(value) {
                        self.intervalY = value
                    }, otherLessThan);
                    compareAndReplace(self.maxY, otherRange.maxY, function(value) {
                        self.maxY = value
                    }, otherGreaterThan);
                    compareAndReplace(self.minVisibleY, otherRange.minVisibleY, function(value) {
                        self.minVisibleY = value
                    }, otherLessThan);
                    compareAndReplace(self.maxVisibleY, otherRange.maxVisibleY, function(value) {
                        self.maxVisibleY = value
                    }, otherGreaterThan);
                    setIndentByPriority('minValueMarginY');
                    setIndentByPriority('maxValueMarginY');
                    if (categoriesY === undefined)
                        self.categoriesY = otherCategoriesY;
                    else if (otherCategoriesY && otherCategoriesY.length)
                        for (i = 0; i < otherCategoriesY.length; i++)
                            if ($.inArray(otherCategoriesY[i], categoriesY) === -1)
                                categoriesY.push(otherCategoriesY[i]);
                    return this
                };
            var getBoundRangeX = function(otherRange) {
                    var self = this,
                        categoriesX = self.categoriesX,
                        otherCategoriesX = otherRange.categoriesX,
                        i;
                    var setIndentByPriority = function(prefix) {
                            var priorityRelation = (self[prefix + 'Priority'] || 0) - (otherRange[prefix + 'Priority'] || 0);
                            if ((self[prefix] || 0) < otherRange[prefix] && priorityRelation === 0 || priorityRelation < 0) {
                                self[prefix] = otherRange[prefix];
                                self[prefix + 'Priority'] = otherRange[prefix + 'Priority']
                            }
                        };
                    self.invertX = self.invertX || otherRange.invertX;
                    self.stickX = self.stickX || otherRange.stickX;
                    self.axisTypeX = self.axisTypeX || otherRange.axisTypeX;
                    if (self.axisTypeX === 'logarithmic')
                        self.baseX = self.baseX || otherRange.baseX;
                    else
                        self.baseX = undefined;
                    self.keepValueMarginsX = self.keepValueMarginsX || otherRange.keepValueMarginsX;
                    compareAndReplace(self.minX, otherRange.minX, function(value) {
                        self.minX = value
                    }, otherLessThan);
                    compareAndReplace(self.intervalX, otherRange.intervalX, function(value) {
                        self.intervalX = value
                    }, otherLessThan);
                    compareAndReplace(self.maxX, otherRange.maxX, function(value) {
                        self.maxX = value
                    }, otherGreaterThan);
                    compareAndReplace(self.minVisibleX, otherRange.minVisibleX, function(value) {
                        self.minVisibleX = value
                    }, otherLessThan);
                    compareAndReplace(self.maxVisibleX, otherRange.maxVisibleX, function(value) {
                        self.maxVisibleX = value
                    }, otherGreaterThan);
                    setIndentByPriority('minValueMarginX');
                    setIndentByPriority('maxValueMarginX');
                    if (categoriesX === undefined)
                        self.categoriesX = otherCategoriesX;
                    else if (otherCategoriesX && otherCategoriesX.length)
                        for (i = 0; i < otherCategoriesX.length; i++)
                            if ($.inArray(otherCategoriesX[i], categoriesX) === -1)
                                categoriesX.push(otherCategoriesX[i]);
                    return this
                };
            var isDefined = function() {
                    return isDefinedX.call(this) || isDefinedY.call(this)
                };
            var isDefinedX = function() {
                    return isDefinedUtils(this.minX) && isDefinedUtils(this.maxX) || isDefinedUtils(this.categoriesX)
                };
            var isDefinedY = function() {
                    return isDefinedUtils(this.minY) && isDefinedUtils(this.maxY) || isDefinedUtils(this.categoriesY)
                };
            var setStubData = function(dataType) {
                    setStubDataX.call(this, dataType);
                    setStubDataY.call(this, dataType)
                };
            var setStubDataX = function(dataType) {
                    var year = (new Date).getYear() - 1;
                    var STUB_RANGE_MIN = dataType === 'datetime' ? new Date(year, 0, 1) : 0,
                        STUB_RANGE_MAX = dataType === 'datetime' ? new Date(year, 11, 31) : 10;
                    $.extend(this, {
                        minX: STUB_RANGE_MIN,
                        maxX: STUB_RANGE_MAX,
                        stubDataX: true
                    })
                };
            var setStubDataY = function(dataType) {
                    var year = (new Date).getYear() - 1;
                    var STUB_RANGE_MIN = dataType === 'datetime' ? new Date(year, 0, 1) : 0,
                        STUB_RANGE_MAX = dataType === 'datetime' ? new Date(year, 11, 31) : 10;
                    $.extend(this, {
                        minY: STUB_RANGE_MIN,
                        maxY: STUB_RANGE_MAX,
                        stubDataY: true
                    })
                };
            var correctValueMarginsToZeroIfNeeded = function(self, field) {
                    var length,
                        min = isDefinedUtils(self['minVisible' + field]) ? self['minVisible' + field] : self['min' + field],
                        max = isDefinedUtils(self['maxVisible' + field]) ? self['maxVisible' + field] : self['max' + field],
                        minValueMargin = self['minValueMargin' + field],
                        maxValueMargin = self['maxValueMargin' + field],
                        isDateTime = isDateUtils(max) || isDateUtils(min);
                    if (isDefinedUtils(max) && isDefinedUtils(min))
                        length = max - min;
                    if (length && !isDateTime && !self['keepValueMargins' + field]) {
                        if (min <= 0 && max <= 0 && maxValueMargin && maxValueMargin > max / (min - max)) {
                            self['maxValueMargin' + field] = 0;
                            self['max' + field] = 0
                        }
                        if (min >= 0 && max >= 0 && minValueMargin && minValueMargin > min / (max - min)) {
                            self['minValueMargin' + field] = 0;
                            self['min' + field] = 0
                        }
                    }
                };
            var applyValueMargins = function() {
                    var self = this,
                        lengthX,
                        lengthY,
                        lengthVisibleX,
                        lengthVisibleY,
                        xDateTime = isDateUtils(self.maxX) || isDateUtils(self.minX),
                        yDateTime = isDateUtils(self.maxY) || isDateUtils(self.minY),
                        minX,
                        maxX,
                        minY,
                        maxY,
                        minValue,
                        minVisibleX,
                        maxVisibleX,
                        minVisibleY,
                        maxVisibleY;
                    if (self.axisTypeX === 'logarithmic') {
                        minX = Math.floor(utils.getLog(self.minX, self.baseX));
                        maxX = Math.ceil(utils.getLog(self.maxX, self.baseX));
                        minVisibleX = Math.floor(utils.getLog(self.minVisibleX, self.baseX));
                        maxVisibleX = Math.ceil(utils.getLog(self.maxVisibleX, self.baseX));
                        if (utils.isDefined(self.minX)) {
                            minValue = self.minX;
                            self.minX = utils.raiseTo(minX, self.baseX);
                            if (utils.getLog(minValue / self.minX, self.baseX) < utils.getLog(1 + self.baseX / 10, self.baseX) && (self.keepValueMarginsX || self.keepValueMarginsY) && !self.keepValueMarginsX) {
                                minX -= 1;
                                self.minX = utils.raiseTo(minX, self.baseX)
                            }
                        }
                        if (!isDefinedUtils(self.minVisibleX) || self.minVisibleX < self.minX || self.minVisibleX > self.maxX)
                            minVisibleX = minX;
                        self.minVisibleX = utils.raiseTo(minVisibleX, self.baseX);
                        if (utils.isDefined(self.maxX))
                            self.maxX = utils.raiseTo(maxX, self.baseX);
                        if (!isDefinedUtils(self.maxVisibleX) || self.maxVisibleX < self.minX || self.maxVisibleX > self.maxX)
                            maxVisibleX = maxX;
                        self.maxVisibleX = utils.raiseTo(maxVisibleX, self.baseX)
                    }
                    else {
                        correctValueMarginsToZeroIfNeeded(self, 'X');
                        if (utils.isDefined(self.maxX) && utils.isDefined(self.minX))
                            lengthX = self.maxX - self.minX;
                        if (!utils.isDefined(self.minVisibleX) || self.minVisibleX < self.minX || self.minVisibleX > self.maxX)
                            self.minVisibleX = self.minX;
                        if (!utils.isDefined(self.maxVisibleX) || self.maxVisibleX < self.minX || self.maxVisibleX > self.maxX)
                            self.maxVisibleX = self.maxX;
                        lengthVisibleX = self.maxVisibleX - self.minVisibleX;
                        if (isDefinedUtils(self.minX) && self.minValueMarginX)
                            if (xDateTime)
                                self.minX = new Date(self.minX.valueOf() - lengthX * self.minValueMarginX);
                            else
                                self.minX -= lengthX * self.minValueMarginX;
                        if (isDefinedUtils(self.minVisibleX) && self.minValueMarginX)
                            if (xDateTime)
                                self.minVisibleX = new Date(self.minVisibleX.valueOf() - lengthVisibleX * self.minValueMarginX);
                            else
                                self.minVisibleX -= lengthVisibleX * self.minValueMarginX;
                        if (isDefinedUtils(self.maxX) && self.maxValueMarginX)
                            if (xDateTime)
                                self.maxX = new Date(self.maxX.valueOf() + lengthX * self.maxValueMarginX);
                            else
                                self.maxX += lengthX * self.maxValueMarginX;
                        if (isDefinedUtils(self.maxVisibleX) && self.maxValueMarginX)
                            if (xDateTime)
                                self.maxVisibleX = new Date(self.maxVisibleX.valueOf() + lengthVisibleX * self.maxValueMarginX);
                            else
                                self.maxVisibleX += lengthVisibleX * self.maxValueMarginX
                    }
                    if (self.axisTypeY === 'logarithmic') {
                        minY = Math.floor(utils.getLog(self.minY, self.baseY));
                        maxY = Math.ceil(utils.getLog(self.maxY, self.baseY));
                        minVisibleY = Math.floor(utils.getLog(self.minVisibleY, self.baseY));
                        maxVisibleY = Math.ceil(utils.getLog(self.maxVisibleY, self.baseY));
                        if (utils.isDefined(self.minY)) {
                            minValue = self.minY;
                            self.minY = utils.raiseTo(minY, self.baseY);
                            if (utils.getLog(minValue / self.minY, self.baseY) < utils.getLog(1 + self.baseY / 10, self.baseY) && (self.keepValueMarginsX || self.keepValueMarginsY) && !self.keepValueMarginsY) {
                                minY -= 1;
                                self.minY = utils.raiseTo(minY, self.baseY)
                            }
                        }
                        if (!utils.isDefined(self.minVisibleY) || self.minVisibleY < self.minY || self.minVisibleY > self.maxY)
                            minVisibleY = minY;
                        self.minVisibleY = utils.raiseTo(minVisibleY, self.baseY);
                        if (utils.isDefined(self.maxY))
                            self.maxY = utils.raiseTo(maxY, self.baseY);
                        if (!utils.isDefined(self.maxVisibleY) || self.maxVisibleY < self.minY || self.maxVisibleY > self.maxY)
                            maxVisibleY = maxY;
                        self.maxVisibleY = utils.raiseTo(maxVisibleY, self.baseY)
                    }
                    else {
                        correctValueMarginsToZeroIfNeeded(self, 'Y');
                        if (utils.isDefined(self.maxY) && utils.isDefined(self.minY))
                            lengthY = self.maxY - self.minY;
                        if (!utils.isDefined(self.minVisibleY) || self.minVisibleY < self.minY || self.minVisibleY > self.maxY)
                            self.minVisibleY = self.minY;
                        if (!utils.isDefined(self.maxVisibleY) || self.maxVisibleY < self.minY || self.maxVisibleY > self.maxY)
                            self.maxVisibleY = self.maxY;
                        lengthVisibleY = self.maxVisibleY - self.minVisibleY;
                        if (isDefinedUtils(self.minY) && self.minValueMarginY)
                            if (yDateTime)
                                self.minY = new Date(self.minY.valueOf() - lengthY * self.minValueMarginY);
                            else
                                self.minY -= lengthY * self.minValueMarginY;
                        if (isDefinedUtils(self.minVisibleY) && self.minValueMarginY)
                            if (yDateTime)
                                self.minVisibleY = new Date(self.minVisibleY.valueOf() - lengthVisibleY * self.minValueMarginY);
                            else
                                self.minVisibleY -= lengthVisibleY * self.minValueMarginY;
                        if (isDefinedUtils(self.maxY) && self.maxValueMarginY)
                            if (yDateTime)
                                self.maxY = new Date(self.maxY.valueOf() + lengthY * self.maxValueMarginY);
                            else
                                self.maxY += lengthY * self.maxValueMarginY;
                        if (isDefinedUtils(self.maxVisibleY) && self.maxValueMarginY)
                            if (yDateTime)
                                self.maxVisibleY = new Date(self.maxVisibleY.valueOf() + lengthVisibleY * self.maxValueMarginY);
                            else
                                self.maxVisibleY += lengthVisibleY * self.maxValueMarginY
                    }
                    self.applyEqualLimitsMargins()
                };
            var applyEqualLimitsMargins = function() {
                    var self = this,
                        xDateTime = isDateUtils(self.maxX) || isDateUtils(self.minX),
                        yDateTime = isDateUtils(self.maxY) || isDateUtils(self.minY);
                    if (isDefinedUtils(self.minX) && isDefinedUtils(self.maxX) && self.minX.valueOf() === self.maxX.valueOf())
                        if (xDateTime) {
                            self.minX = new Date(self.minX.valueOf() - DATETIME_EQUALITY_CORRECTION);
                            self.maxX = new Date(self.maxX.valueOf() + DATETIME_EQUALITY_CORRECTION)
                        }
                        else {
                            self.minX = self.minX - NUMBER_EQUALITY_CORRECTION;
                            self.maxX = self.maxX + NUMBER_EQUALITY_CORRECTION
                        }
                    if (isDefinedUtils(self.minVisibleX) && isDefinedUtils(self.maxVisibleX) && self.minVisibleX.valueOf() === self.maxVisibleX.valueOf())
                        if (xDateTime) {
                            self.minVisibleX = self.minVisibleX.valueOf() - DATETIME_EQUALITY_CORRECTION < self.minX.valueOf() ? self.minX : new Date(self.minVisibleX.valueOf() - DATETIME_EQUALITY_CORRECTION);
                            self.maxVisibleX = self.maxVisibleX.valueOf() + DATETIME_EQUALITY_CORRECTION > self.maxX.valueOf() ? self.maxX : new Date(self.maxVisibleX.valueOf() + DATETIME_EQUALITY_CORRECTION)
                        }
                        else {
                            self.minVisibleX = self.minVisibleX - NUMBER_EQUALITY_CORRECTION < self.minX ? self.minX : self.minVisibleX - NUMBER_EQUALITY_CORRECTION;
                            self.maxVisibleX = self.maxVisibleX + NUMBER_EQUALITY_CORRECTION > self.maxX ? self.maxX : self.maxVisibleX + NUMBER_EQUALITY_CORRECTION
                        }
                    if (isDefinedUtils(self.minY) && isDefinedUtils(self.maxY) && self.minY.valueOf() === self.maxY.valueOf())
                        if (yDateTime) {
                            self.minY = new Date(self.minY.valueOf() - DATETIME_EQUALITY_CORRECTION);
                            self.maxY = new Date(self.maxY.valueOf() + DATETIME_EQUALITY_CORRECTION)
                        }
                        else {
                            self.minY = self.minY === 0 ? self.minY : self.minY - NUMBER_EQUALITY_CORRECTION;
                            self.maxY = self.maxY + NUMBER_EQUALITY_CORRECTION
                        }
                    if (isDefinedUtils(self.minVisibleY) && isDefinedUtils(self.maxVisibleY) && self.minVisibleY.valueOf() === self.maxVisibleY.valueOf())
                        if (yDateTime) {
                            self.minVisibleY = self.minVisibleY.valueOf() - DATETIME_EQUALITY_CORRECTION < self.minY.valueOf() ? self.minY : new Date(self.minVisibleY.valueOf() - DATETIME_EQUALITY_CORRECTION);
                            self.maxVisibleY = self.maxVisibleY.valueOf() + DATETIME_EQUALITY_CORRECTION > self.maxY.valueOf() ? self.maxY : new Date(self.maxVisibleY.valueOf() + DATETIME_EQUALITY_CORRECTION)
                        }
                        else {
                            if (self.minVisibleY !== 0)
                                self.minVisibleY = self.minVisibleY - NUMBER_EQUALITY_CORRECTION < self.minY ? self.minY : self.minVisibleY - NUMBER_EQUALITY_CORRECTION;
                            self.maxVisibleY = self.maxVisibleY + NUMBER_EQUALITY_CORRECTION > self.maxY ? self.maxY : self.maxVisibleY + NUMBER_EQUALITY_CORRECTION
                        }
                };
            var correctValueZeroLevel = function() {
                    var self = this;
                    if (isDateUtils(self.maxY) || isDateUtils(self.minY))
                        return;
                    function setZeroLevel(min, max) {
                        self[min] < 0 && self[max] < 0 && (self[max] = 0);
                        self[min] > 0 && self[max] > 0 && (self[min] = 0)
                    }
                    setZeroLevel("minY", "maxY");
                    setZeroLevel("minVisibleY", "maxVisibleY")
                };
            return {
                    ctor: ctor,
                    dispose: dispose,
                    getBoundRange: getBoundRange,
                    getBoundRangeX: getBoundRangeX,
                    getBoundRangeY: getBoundRangeY,
                    isDefined: isDefined,
                    isDefinedX: isDefinedX,
                    isDefinedY: isDefinedY,
                    setStubData: setStubData,
                    setStubDataX: setStubDataX,
                    setStubDataY: setStubDataY,
                    applyValueMargins: applyValueMargins,
                    applyEqualLimitsMargins: applyEqualLimitsMargins,
                    correctValueZeroLevel: correctValueZeroLevel
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-core, file chartsConsts.js */
    (function(DX) {
        DX.viz.charts.consts = {
            dataTypes: {
                STRING: 'string',
                NUMERIC: 'numeric',
                DATETIME: 'datetime'
            },
            axisTypes: {
                DISCRETE: 'discrete',
                CONTINUOUS: 'continuous',
                LOGARITHMIC: 'logarithmic'
            }
        }
    })(DevExpress);
    /*! Module viz-core, file dataValidator.js */
    (function($, DX) {
        var viz = DX.viz,
            parseUtils = new viz.core.ParseUtils,
            chartConst = viz.charts.consts,
            dataTypes = chartConst.dataTypes,
            axisTypes = chartConst.axisTypes,
            utils = DX.utils;
        viz.charts.DataValidator = DX.Class.inherit({
            ctor: function(data, groups, incidentOccured, dataPrepareOptions) {
                var _this = this;
                groups = groups || [[]];
                if (!data)
                    _this._nullData = true;
                _this.groups = groups;
                _this.data = data || [];
                _this._parsers = {};
                _this._errorShowList = {};
                _this._skipFields = {};
                _this.options = dataPrepareOptions || {};
                _this.incidentOccured = incidentOccured;
                _this.userArgumentCategories = _this.groups.length && _this.groups[0].length && _this.groups[0][0].options.argumentCategories;
                if (_this.incidentOccured)
                    _this.incidentOccured = function() {
                        incidentOccured.apply(null, arguments)
                    };
                else
                    _this.incidentOccured = $.noop
            },
            validate: function validate() {
                var _this = this;
                _this._data = _this.data;
                if (!utils.isArray(_this.data) || _this._nullData)
                    _this.incidentOccured(_this._errorMessages.incorrectDataMessage.apply(_this));
                _this._checkType();
                _this._checkAxisType();
                if (_this.options.convertToAxisDataType) {
                    _this._createParser();
                    _this._parse()
                }
                _this._sort();
                $.each(_this._skipFields, function(field, fieldValue) {
                    if (fieldValue === _this._data.length)
                        _this.incidentOccured(_this._errorMessages.missingFieldMessage(field))
                });
                return _this._data
            },
            _checkType: function _checkType() {
                var _this = this,
                    groupsWithUndefinedValueType = [],
                    groupsWithUndefinedArgumentType = [],
                    checkValueTypeOfGroup = function checkValueTypeOfGroup(group, cell) {
                        $.each(group, function(_, series) {
                            $.each(series.getValueFields(), function(_, field) {
                                group.valueType = _this._getType(cell[field], group.valueType)
                            })
                        });
                        if (group.valueType)
                            return true
                    },
                    checkArgumentTypeOfGroup = function checkArgumentTypeOfGroup(group, cell) {
                        $.each(group, function(_, series) {
                            var field = series.getArgumentField();
                            _this.groups.argumentType = _this._getType(cell[field], _this.groups.argumentType)
                        });
                        if (_this.groups.argumentType)
                            return true
                    };
                $.each(_this.groups, function(_, group) {
                    if (!group.length)
                        return null;
                    var valueTypeGroup = group[0].options.valueType,
                        argumentTypeGroup = group[0].options.argumentType;
                    group.valueType = valueTypeGroup;
                    _this.groups.argumentType = argumentTypeGroup;
                    valueTypeGroup ? null : groupsWithUndefinedValueType.push(group);
                    argumentTypeGroup ? null : groupsWithUndefinedArgumentType.push(group)
                });
                if (groupsWithUndefinedValueType.length || groupsWithUndefinedArgumentType.length)
                    $.each(_this.data, function(_, cell) {
                        var define = true;
                        if (!utils.isObject(cell))
                            return;
                        $.each(groupsWithUndefinedValueType, function(index, group) {
                            define = define && checkValueTypeOfGroup(group, cell)
                        });
                        $.each(groupsWithUndefinedArgumentType, function(index, group) {
                            define = define && checkArgumentTypeOfGroup(group, cell)
                        });
                        if (!_this.options.checkTypeForAllData && define)
                            return false
                    })
            },
            _checkAxisType: function _checkAxisType() {
                var _this = this;
                $.each(_this.groups, function(_, group) {
                    $.each(group, function(_, series) {
                        var optionsSeries = {};
                        optionsSeries.argumentAxisType = _this._correctAxisType(_this.groups.argumentType, series.options.argumentAxisType, !!(_this.userArgumentCategories && _this.userArgumentCategories.length));
                        optionsSeries.valueAxisType = _this._correctAxisType(group.valueType, series.options.valueAxisType, !!(series.options.valueCategories && series.options.valueCategories.length));
                        _this.groups.argumentAxisType = _this.groups.argumentAxisType || series.options.argumentAxisType;
                        optionsSeries.argumentType = _this.groups.argumentType;
                        optionsSeries.valueType = group.valueType;
                        series._updateDataType(optionsSeries)
                    })
                })
            },
            _createParser: function _createParser() {
                var _this = this;
                $.each(_this.groups, function(index, group) {
                    $.each(group, function(_, series) {
                        _this._parsers[series.getArgumentField()] = _this._createParserUnit(_this.groups.argumentType, _this.groups.argumentAxisType === axisTypes.LOGARITHMIC ? _this._filterForLogAxis : null);
                        $.each(series.getValueFields(), function(_, field) {
                            _this._parsers[field] = _this._createParserUnit(group.valueType, series.options.valueAxisType === axisTypes.LOGARITHMIC ? _this._filterForLogAxis : null)
                        });
                        if (series.getTagField())
                            _this._parsers[series.getTagField()] = null
                    })
                })
            },
            _parse: function _parse() {
                var _this = this,
                    parsedData = [];
                $.each(_this.data, function(_, cell) {
                    var parserObject = {};
                    if (!utils.isObject(cell)) {
                        cell && _this.incidentOccured(_this._errorMessages.incorrectDataMessage.apply(_this));
                        return
                    }
                    $.each(_this._parsers, function(field, parser) {
                        parserObject[field] = parser ? parser(cell[field], field) : cell[field];
                        parserObject['original' + field] = cell[field]
                    });
                    parsedData.push(parserObject)
                });
                this._data = parsedData
            },
            _getType: function _getType(unit, type) {
                if (type === dataTypes.STRING || utils.isString(unit))
                    return dataTypes.STRING;
                if (type === dataTypes.DATETIME || utils.isDate(unit))
                    return dataTypes.DATETIME;
                if (utils.isNumber(unit))
                    return dataTypes.NUMERIC;
                return type
            },
            _correctAxisType: function _correctAxisType(type, axisType, hasCategories) {
                if (type === dataTypes.STRING && (axisType === axisTypes.CONTINUOUS || axisType === axisTypes.LOGARITHMIC))
                    this.incidentOccured(this._errorMessages.incompatibleTypesDataMessage());
                if (axisType === axisTypes.LOGARITHMIC)
                    return axisTypes.LOGARITHMIC;
                axisType = (hasCategories || axisType === axisTypes.DISCRETE || type === dataTypes.STRING) && axisTypes.DISCRETE;
                return axisType || axisTypes.CONTINUOUS
            },
            _filterForLogAxis: function(val, field) {
                if (val <= 0) {
                    this.incidentOccured(this._errorMessages.numericParsingMessage(field, val));
                    return null
                }
                return val
            },
            _createParserUnit: function _createParserUnit(type, filter) {
                var _this = this,
                    parser = type ? parseUtils.getParser(type, undefined, true) : function(unit) {
                        return unit
                    };
                return function(unit, field) {
                        var parseUnit = parser(unit);
                        if (filter)
                            parseUnit = filter.call(_this, parseUnit, field);
                        if (parseUnit === undefined) {
                            _this._addSkipFields(field);
                            _this._validUnit(unit, field, type)
                        }
                        return parseUnit
                    }
            },
            _validUnit: function _validUnit(unit, field, type) {
                if (!unit)
                    return;
                (unit.length || !utils.isDate(unit)) && this.incidentOccured(this._errorMessages.unsupportedFieldMessage(field));
                type === dataTypes.NUMERIC ? this.incidentOccured(this._errorMessages.numericParsingMessage(field)) : this.incidentOccured(this._errorMessages.dateParsingMessage(field))
            },
            _sort: function _sort() {
                var _this = this,
                    groups = _this.groups,
                    hash = {},
                    argumentField = groups.length && groups[0].length && groups[0][0].getArgumentField();
                if (utils.isFunction(_this.options.sortingMethod))
                    _this._data.sort(_this.options.sortingMethod);
                else if (_this.userArgumentCategories) {
                    $.each(_this.userArgumentCategories, function(index, value) {
                        hash[value] = index
                    });
                    _this._data.sort(function sortCat(a, b) {
                        a = a[argumentField];
                        b = b[argumentField];
                        return hash[a] - hash[b]
                    })
                }
                else if (_this.options.sortingMethod === true && groups.argumentType !== dataTypes.STRING)
                    _this._data.sort(function(a, b) {
                        return a[argumentField] - b[argumentField]
                    })
            },
            _addSkipFields: function _addSkipFields(field) {
                this._skipFields[field] = (this._skipFields[field] || 0) + 1
            },
            _errorMessages: {
                missingFieldMessage: function(field) {
                    return "Data source does not contain the '" + field + "' field."
                },
                unsupportedFieldMessage: function(field) {
                    return "The '" + field + "' field contains data of unsupported type."
                },
                incorrectDataMessage: function() {
                    if (this._erorrDataSource !== true) {
                        this._erorrDataSource = true;
                        return "Data source contains unsupported data."
                    }
                },
                incompatibleTypesDataMessage: function() {
                    return "The axis type and data type are incompatible."
                },
                numericParsingMessage: function(field, count) {
                    return "Value of the '" + field + "' field cannot be parsed to a correct numeric"
                },
                dateParsingMessage: function(field, count) {
                    return "Value of the '" + field + "' field cannot be parsed to a correct date."
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file themeManager.js */
    (function($, DX, undefined) {
        var viz = DX.viz,
            Palette = viz.core.Palette,
            isArray = DX.utils.isArray;
        var HOVER_COLOR_HIGHLIGHTING = 20,
            HIGHLIGHTING_STEP = 50;
        viz.charts.ThemeManager = viz.core.BaseThemeManager.inherit(function() {
            var ctor = function(options, themeGroupName) {
                    var _this = this;
                    _this.isIE8 = DX.browser.msie && DX.browser.version < 9;
                    options = options || {};
                    _this.callBase(options.theme, themeGroupName || 'chart');
                    _this.palette = new Palette(options.palette || _this.theme.defaultPalette, HIGHLIGHTING_STEP, _this.themeName);
                    _this.init()
                };
            var dispose = function() {
                    this.palette.dispose();
                    this.palette = null;
                    this.callBase()
                };
            var init = function() {
                    var _this = this;
                    _this.theme.legend = _this.theme.legend || {};
                    _this.theme.legend.font = _this.theme.legend.font || {};
                    _this.initializeFont(_this.theme.legend.font);
                    initDefaultSeriesTheme(_this);
                    initAxisTheme(_this);
                    _this.theme.title = _this.theme.title || {};
                    _this.theme.title.font = _this.theme.title.font || {};
                    _this.initializeFont(_this.theme.title.font);
                    _this.theme.tooltip = _this.theme.tooltip || {};
                    _this.theme.tooltip.font = _this.theme.tooltip.font || {};
                    _this.initializeFont(_this.theme.tooltip.font)
                };
            var initDefaultSeriesTheme = function(self) {
                    var theme = self.theme,
                        commonSeriesSettings = theme.commonSeriesSettings,
                        fontOptions = theme.font,
                        pointTheme;
                    commonSeriesSettings.point = commonSeriesSettings.point || {};
                    commonSeriesSettings.containerBackgroundColor = commonSeriesSettings.containerBackgroundColor || theme.containerBackgroundColor;
                    commonSeriesSettings.label = commonSeriesSettings.label || {};
                    self.initializeFont(commonSeriesSettings.label.font)
                };
            var initAxisTheme = function(self) {
                    var theme = self.theme,
                        axisTheme = theme.commonAxisSettings,
                        fontOptions = theme.font,
                        titleTheme,
                        labelTheme;
                    if (axisTheme) {
                        axisTheme.label = axisTheme.label || {};
                        axisTheme.grid = axisTheme.grid || {};
                        axisTheme.ticks = axisTheme.ticks || {};
                        axisTheme.line = axisTheme.line || {};
                        axisTheme.title = axisTheme.title || {};
                        axisTheme.label.font = axisTheme.label.font || {};
                        self.initializeFont(axisTheme.label.font);
                        axisTheme.title.font = axisTheme.title.font || {};
                        self.initializeFont(axisTheme.title.font)
                    }
                };
            var applyChartTheme = function(userOptions) {
                    var self = this,
                        refs = {
                            dataSource: userOptions.dataSource,
                            series: userOptions.series
                        },
                        result;
                    delete userOptions.dataSource;
                    delete userOptions.series;
                    if (userOptions.valueAxis && isArray(userOptions.valueAxis) && !userOptions.valueAxis.length || $.isEmptyObject(userOptions.valueAxis))
                        delete userOptions.valueAxis;
                    if (userOptions.panes && isArray(userOptions.panes) && !userOptions.panes.length || $.isEmptyObject(userOptions.panes))
                        delete userOptions.panes;
                    result = self.applyTheme(self.theme, userOptions);
                    result.dataSource = refs.dataSource;
                    result.series = refs.series;
                    userOptions.series = refs.series;
                    userOptions.dataSource = refs.dataSource;
                    return result
                };
            var applyNextSeriesTheme = function(userOptions, commonSeriesSettings, userCommonSeriesSettings) {
                    var debug = DX.utils.debug;
                    debug.assertParam(userOptions, 'User options were not passed');
                    if (commonSeriesSettings) {
                        debug.assertParam(commonSeriesSettings.hoverStyle, 'hoverStyle option was not passed');
                        debug.assertParam(commonSeriesSettings.selectionStyle, 'selectionStyle option was not passed');
                        debug.assertParam(commonSeriesSettings.point, 'point option was not passed');
                        debug.assertParam(commonSeriesSettings.point.hoverStyle, 'point.hoverStyle option was not passed');
                        debug.assertParam(commonSeriesSettings.point.selectionStyle, 'point.selectionStyle option was not passed')
                    }
                    var self = this,
                        mergedSettings = $.extend(true, {}, commonSeriesSettings || self.theme.commonSeriesSettings),
                        mergedUserSettings = $.extend(true, {}, userCommonSeriesSettings || {}),
                        seriesType = ((userOptions.type || mergedSettings.type || '') + '').toLowerCase(),
                        isBar = ~seriesType.indexOf('bar'),
                        isBubble = ~seriesType.indexOf('bubble'),
                        isArea = ~seriesType.indexOf('area'),
                        mainSeriesColor,
                        mainPointColor;
                    mergedUserSettings = $.extend(true, mergedUserSettings, mergedUserSettings[seriesType]);
                    mergedSettings = $.extend(true, mergedSettings, mergedSettings[seriesType], mergedUserSettings);
                    userOptions = userOptions || {};
                    if (isBar || isBubble)
                        $.extend(true, userOptions, mergedUserSettings.point, userOptions.point);
                    mainSeriesColor = new DX.Color(userOptions.color || mergedUserSettings.color || self.palette.getNextColor());
                    mergedSettings.color = mainSeriesColor.toHex();
                    mergedSettings.border.color = mergedSettings.border.color || mainSeriesColor.toHex();
                    mergedSettings.hoverStyle.color = mergedSettings.hoverStyle.color || self.isIE8 && (isBar || isBubble || isArea) && mainSeriesColor.highlight(HOVER_COLOR_HIGHLIGHTING) || mainSeriesColor.toHex();
                    mergedSettings.hoverStyle.border.color = mergedSettings.hoverStyle.border.color || mainSeriesColor.toHex();
                    mergedSettings.selectionStyle.color = mergedSettings.selectionStyle.color || self.isIE8 && (isBar || isBubble || isArea) && mainSeriesColor.highlight(HOVER_COLOR_HIGHLIGHTING) || mainSeriesColor.toHex();
                    mergedSettings.selectionStyle.border.color = mergedSettings.selectionStyle.border.color || mainSeriesColor.toHex();
                    mainPointColor = new DX.Color(userOptions.point && userOptions.point.color || mergedUserSettings.point && mergedUserSettings.point.color || mainSeriesColor.toHex());
                    mergedSettings.point.color = mainPointColor.toHex();
                    mergedSettings.point.border.color = mergedSettings.point.border.color || isBar && mergedSettings.border.color || mainPointColor.toHex();
                    mergedSettings.point.hoverStyle.color = mergedSettings.point.hoverStyle.color || isBar && mergedSettings.hoverStyle.color || mergedSettings.containerBackgroundColor;
                    mergedSettings.point.hoverStyle.border.color = mergedSettings.point.hoverStyle.border.color || isBar && mergedSettings.hoverStyle.border.color || mainPointColor.toHex();
                    mergedSettings.point.selectionStyle.color = mergedSettings.point.selectionStyle.color || isBar && mergedSettings.selectionStyle.color || mergedSettings.containerBackgroundColor;
                    mergedSettings.point.selectionStyle.border.color = mergedSettings.point.selectionStyle.border.color || isBar && mergedSettings.selectionStyle.border.color || mainPointColor.toHex();
                    return self.applyTheme(mergedSettings, userOptions)
                };
            var applyPieSeriesTheme = function applyPieSeriesTheme(userOptions, commonSeriesSettings, userCommonSeriesSettings) {
                    var self = this,
                        commonSettings = commonSeriesSettings || self.theme.commonSeriesSettings || {},
                        seriesType = (userOptions.type || commonSettings.type || '').toLowerCase();
                    if (seriesType && seriesType !== 'pie')
                        commonSettings[seriesType] = $.extend(true, {}, commonSettings[seriesType], commonSettings.pie);
                    userCommonSeriesSettings = userCommonSeriesSettings || {};
                    userOptions = userOptions || {};
                    userOptions = $.extend(true, {}, commonSettings, commonSettings[seriesType], userCommonSeriesSettings, userCommonSeriesSettings[seriesType], userOptions);
                    return userOptions
                };
            var applyNextPieSegmentTheme = function applyNextPieSegmentTheme(userOptions, commonSeriesSettings) {
                    var self = this,
                        commonSettings = commonSeriesSettings || self.theme.commonSeriesSettings || {},
                        mergedSettings = $.extend(true, {}, commonSettings.pie),
                        seriesType = userOptions.type || mergedSettings.type || '';
                    userOptions = userOptions || {};
                    var mainColor = new DX.Color(userOptions.color || self.palette.getNextColor());
                    mergedSettings.color = mainColor.toHex();
                    mergedSettings.border.color = mergedSettings.border.color || mainColor.toHex();
                    mergedSettings.hoverStyle.color = mergedSettings.hoverStyle.color || self.isIE8 && mainColor.highlight(HOVER_COLOR_HIGHLIGHTING) || mainColor.toHex();
                    mergedSettings.hoverStyle.border.color = mergedSettings.hoverStyle.border.color || mainColor.toHex();
                    mergedSettings.selectionStyle.color = mergedSettings.selectionStyle.color || self.isIE8 && mainColor.highlight(HOVER_COLOR_HIGHLIGHTING) || mainColor.toHex();
                    mergedSettings.selectionStyle.border.color = mergedSettings.selectionStyle.border.color || mainColor.toHex();
                    return self.applyTheme(mergedSettings, userOptions)
                };
            var resetPalette = function() {
                    this.palette.reset()
                };
            var updatePalette = function(palette) {
                    this.palette = new Palette(palette || this.theme.defaultPalette, HIGHLIGHTING_STEP, this.themeName)
                };
            return {
                    ctor: ctor,
                    dispose: dispose,
                    init: init,
                    applyChartTheme: applyChartTheme,
                    applyNextSeriesTheme: applyNextSeriesTheme,
                    applyPieSeriesTheme: applyPieSeriesTheme,
                    applyNextPieSegmentTheme: applyNextPieSegmentTheme,
                    resetPalette: resetPalette,
                    updatePalette: updatePalette
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-core, file tooltip.js */
    (function($, DX, undefined) {
        var formatHelper = DX.formatHelper;
        var ARROW_WIDTH = 20;
        DX.viz.charts.Tooltip = DX.Class.inherit({
            ctor: function(options, group) {
                this.textStyle = {align: 'center'};
                this.tooltipGroup = group;
                this._reinit(options)
            },
            dispose: function() {
                this.shadow = null;
                this.cloud = null;
                this.text = null;
                this.tooltipGroup = null;
                this.options = null;
                this.textStyle = null;
                this.renderer = null
            },
            update: function(options) {
                this._reinit(options)
            },
            _reinit: function(options) {
                options = options || {};
                this.renderer = options.renderer || this.renderer;
                this.customColor = options.color || this.customColor;
                this.textStyle.font = options.font || this.textStyle.font;
                this.canvasWidth = options.canvasWidth || this.canvasWidth;
                this.canvasHeight = options.canvasHeight || this.canvasHeight;
                delete options.renderer;
                delete options.font;
                this.options = $.extend(true, {}, this.options || {}, options)
            },
            formatValueTooltip: function(options) {
                return formatHelper.format(this.value, options.format, options.precision)
            },
            formatTooltip: function(options) {
                var formatTooltipValues = function(point) {
                        point.argumentText = formatHelper.format(point.argument, options.argumentFormat, options.argumentPrecision);
                        if (point.percent !== undefined)
                            point.percentText = formatHelper.format(point.percent, 'percent', options.percentPrecision);
                        if (point.total !== undefined)
                            point.totalText = formatHelper.format(point.total, options.format, options.precision)
                    };
                formatTooltipValues(this);
                $.each(this.points || [], function(_, point) {
                    formatTooltipValues(point)
                });
                return options.customizeText ? options.customizeText.call(this, this) : this.valueText
            },
            _getData: function() {
                var _this = this,
                    x = _this.x,
                    y = _this.y,
                    xt = x,
                    yt = y,
                    i,
                    align = 'center',
                    pointsOfShadow = [],
                    points = [],
                    bbox = _this.text.getBBox(),
                    options = _this.options,
                    paddingLeftRight = options.paddingLeftRight,
                    paddingTopBottom = options.paddingTopBottom,
                    arrowLength = options.arrowLength > 0 ? options.arrowLength : 0,
                    horPosition = options.cloudHorizontalPosition,
                    verPosition = options.cloudVerticalPosition,
                    isHorPositionDefined = horPosition !== undefined && horPosition !== null,
                    isVerPositionDefined = verPosition !== undefined && verPosition !== null,
                    cloudWidth = bbox.width + paddingLeftRight * 2,
                    cloudHeight = bbox.height + paddingTopBottom * 2,
                    updatedText;
                updatedText = _this._checkWidthText(cloudWidth, cloudHeight);
                if (updatedText) {
                    bbox = updatedText.bbox;
                    cloudWidth = updatedText.cloudWidth;
                    cloudHeight = updatedText.cloudHeight;
                    paddingLeftRight = updatedText.paddingLeftRight;
                    paddingTopBottom = updatedText.paddingTopBottom
                }
                if (isHorPositionDefined ? horPosition === 'right' : cloudWidth / 2 > x) {
                    points = _this._setArrowLeft(cloudWidth, cloudHeight, arrowLength, x, y);
                    align = 'left';
                    xt += paddingLeftRight
                }
                else if (isHorPositionDefined ? horPosition === 'left' : x + cloudWidth / 2 > _this.canvasWidth) {
                    points = _this._setArrowRight(cloudWidth, cloudHeight, arrowLength, x, y);
                    align = 'right';
                    xt -= paddingLeftRight
                }
                else
                    points = _this._setArrowCenter(cloudWidth, cloudHeight, arrowLength, x, y);
                if (isVerPositionDefined ? verPosition === 'top' : cloudHeight + arrowLength < y) {
                    yt -= arrowLength + cloudHeight / 2 - bbox.height / 2 + _this.tooltipOffset;
                    _this.tooltipInverted = false
                }
                else {
                    yt += arrowLength + cloudHeight / 2 + bbox.height / 2 + _this.tooltipOffset;
                    _this.tooltipInverted = true
                }
                $.extend(pointsOfShadow, points);
                if (arrowLength > 0 && !_this.tooltipInverted) {
                    if (cloudHeight + arrowLength < y)
                        pointsOfShadow[1] += 2;
                    if (cloudWidth / 2 > x)
                        pointsOfShadow[2] += 2;
                    else if (x + cloudWidth / 2 > _this.canvasWidth)
                        pointsOfShadow[pointsOfShadow.length - 2] -= 2;
                    else {
                        pointsOfShadow[2] += 2;
                        pointsOfShadow[pointsOfShadow.length - 2] -= 2
                    }
                }
                else if (_this.tooltipInverted)
                    if (x + cloudWidth / 2 < _this.canvasWidth)
                        pointsOfShadow[1] = pointsOfShadow[3];
                return {
                        points: points,
                        text: {
                            x: xt,
                            y: yt,
                            align: align
                        },
                        pointsOfShadow: pointsOfShadow
                    }
            },
            _updateTooltip: function() {
                var _this = this,
                    box,
                    data,
                    SHADOW_OFFSET = 4,
                    scale;
                _this.text.updateText(_this.tooltipText);
                _this.text.applySettings({font: _this.textStyle.font});
                data = _this._getData();
                _this.shadow.applySettings({points: data.pointsOfShadow});
                _this.shadow.move(_this.tooltipInverted ? SHADOW_OFFSET : 0, SHADOW_OFFSET);
                _this.cloud.applySettings({
                    points: data.points,
                    fill: _this.fillColor,
                    'class': _this.className
                });
                _this.text.applySettings({y: data.text.y});
                box = _this.text.getBBox();
                _this.text.applySettings({
                    x: data.text.x,
                    y: data.text.y - (box.y + box.height - data.text.y),
                    align: data.text.align
                });
                box = _this.tooltipGroup.getBBox();
                if (box.y + box.height > _this.canvasHeight) {
                    scale = (_this.canvasHeight - box.y) / box.height;
                    _this.tooltipGroup.applySettings({
                        scale: scale,
                        translateX: _this.x * (1 - scale),
                        translateY: _this.y * (1 - scale)
                    })
                }
                else
                    _this.tooltipGroup.applySettings({
                        scale: 1,
                        translateX: 0,
                        translateY: 0
                    })
            },
            draw: function() {
                if (!this.shadow) {
                    this.shadow = this.renderer.createPath({}, {
                        fill: '#000000',
                        stroke: 'none',
                        opacity: 0.1
                    });
                    this.cloud = this.renderer.createArea({}, {fill: this.customColor});
                    this.text = this.renderer.createText('0', 0, 0, this.textStyle)
                }
                this.shadow.append(this.tooltipGroup);
                this.cloud.append(this.tooltipGroup);
                this.text.append(this.tooltipGroup);
                this.hide()
            },
            show: function() {
                var options = {visibility: 'visible'};
                this.shadow.applySettings(options);
                this.cloud.applySettings(options);
                this.text.applySettings(options)
            },
            hide: function() {
                var options = {visibility: 'hidden'};
                this.shadow.applySettings(options);
                this.cloud.applySettings(options);
                this.text.applySettings(options)
            },
            move: function(x, y, offset, text, color, className) {
                this.x = x;
                this.y = y;
                this.tooltipOffset = offset;
                this.tooltipText = text;
                this.fillColor = this.customColor || color;
                this.className = className;
                this._updateTooltip()
            },
            _setArrowCenter: function(cloudWidth, cloudHeight, arrowLength, x, y) {
                var _this = this,
                    position = _this.options.cloudVerticalPosition,
                    isPosDefined = position !== undefined && position !== null,
                    verticalInvert = !(isPosDefined ? position === 'top' : cloudHeight + arrowLength < y),
                    x0 = x,
                    y0 = verticalInvert ? y + _this.tooltipOffset : y - _this.tooltipOffset,
                    x1 = x0 + ARROW_WIDTH / 2,
                    y1 = verticalInvert ? y0 + arrowLength : y0 - arrowLength,
                    x2 = x1 + cloudWidth / 2 - ARROW_WIDTH / 2,
                    y2 = y1,
                    x3 = x2,
                    y3 = verticalInvert ? y2 + cloudHeight : y2 - cloudHeight,
                    x4 = x3 - cloudWidth,
                    y4 = y3,
                    x5 = x4,
                    y5 = verticalInvert ? y4 - cloudHeight : y4 + cloudHeight,
                    x6 = x5 + cloudWidth / 2 - ARROW_WIDTH / 2,
                    y6 = y5;
                return [x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6]
            },
            _setArrowLeft: function(cloudWidth, cloudHeight, arrowLength, x, y) {
                var _this = this,
                    position = _this.options.cloudVerticalPosition,
                    isPosDefined = position !== undefined && position !== null,
                    verticalInvert = !(isPosDefined ? position === 'top' : cloudHeight + arrowLength < y),
                    x0 = x,
                    y0 = verticalInvert ? y + _this.tooltipOffset : y - _this.tooltipOffset,
                    x1 = x0 + ARROW_WIDTH,
                    y1 = verticalInvert ? y0 + arrowLength : y0 - arrowLength,
                    x2 = x1 + cloudWidth - ARROW_WIDTH,
                    y2 = y1,
                    x3 = x2,
                    y3 = verticalInvert ? y2 + cloudHeight : y2 - cloudHeight,
                    x4 = x3 - cloudWidth,
                    y4 = y3,
                    x5 = x4,
                    y5 = verticalInvert ? y4 - cloudHeight - arrowLength : y4 + cloudHeight + arrowLength;
                return [x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5]
            },
            _setArrowRight: function(cloudWidth, cloudHeight, arrowLength, x, y) {
                var _this = this,
                    position = _this.options.cloudVerticalPosition,
                    isPosDefined = position !== undefined && position !== null,
                    verticalInvert = !(isPosDefined ? position === 'top' : cloudHeight + arrowLength < y),
                    x0 = x,
                    y0 = verticalInvert ? y + _this.tooltipOffset : y - _this.tooltipOffset,
                    x1 = x0,
                    y1 = verticalInvert ? y0 + arrowLength + cloudHeight : y0 - arrowLength - cloudHeight,
                    x2 = x1 - cloudWidth,
                    y2 = y1,
                    x3 = x2,
                    y3 = verticalInvert ? y2 - cloudHeight : y2 + cloudHeight,
                    x4 = x3 + cloudWidth - ARROW_WIDTH,
                    y4 = y3,
                    x5 = x4 + ARROW_WIDTH,
                    y5 = verticalInvert ? y4 - arrowLength : y4 + arrowLength;
                return [x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5]
            },
            _checkWidthText: function(cloudWidth, cloudHeight) {
                var x = this.x,
                    y = this.y,
                    text = this.tooltipText,
                    index,
                    paddingLeftRight = this.options.paddingLeftRight,
                    paddingTopBottom = this.options.paddingTopBottom,
                    textLength,
                    maxTooltipWidth,
                    remainLength,
                    newIndex,
                    bbox = this.text.getBBox();
                if (cloudWidth < x || x + cloudWidth < this.canvasWidth || cloudWidth / 2 < x && x + cloudWidth / 2 < this.canvasWidth)
                    return false;
                if (text.indexOf("<br/>") === -1 && text.indexOf(" ") !== -1) {
                    maxTooltipWidth = Math.max(x, this.canvasWidth - x, 2 * Math.min(x, this.canvasWidth - x));
                    textLength = text.length * maxTooltipWidth / bbox.width;
                    index = text.substr(0, ~~textLength).lastIndexOf(" ");
                    if (index === -1)
                        index = text.substr(0).indexOf(" ");
                    remainLength = text.substr(index + 1).length;
                    this.tooltipText = text.substr(0, index) + "<br/>";
                    while (textLength <= remainLength) {
                        newIndex = text.substr(index + 1, ~~textLength).lastIndexOf(" ");
                        if (newIndex === -1)
                            newIndex = text.substr(index + 1).indexOf(" ");
                        if (newIndex !== -1) {
                            this.tooltipText += text.substr(index + 1, newIndex) + "<br/>";
                            remainLength = text.substr(index + 1 + newIndex).length;
                            index += newIndex + 1
                        }
                        else
                            break
                    }
                    this.tooltipText += text.substr(index + 1);
                    this.text.updateText(this.tooltipText);
                    bbox = this.text.getBBox();
                    cloudWidth = bbox.width + paddingLeftRight * 2;
                    cloudHeight = bbox.height + paddingTopBottom * 2
                }
                if (cloudWidth > x && x + cloudWidth > this.canvasWidth && (cloudWidth / 2 > x || x + cloudWidth / 2 > this.canvasWidth)) {
                    paddingLeftRight = 5;
                    paddingTopBottom = 5;
                    cloudWidth = bbox.width + 2 * paddingLeftRight;
                    cloudHeight = bbox.height + 2 * paddingTopBottom
                }
                return {
                        bbox: bbox,
                        cloudWidth: cloudWidth,
                        cloudHeight: cloudHeight,
                        paddingTopBottom: paddingTopBottom,
                        paddingLeftRight: paddingLeftRight
                    }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file seriesConsts.js */
    (function(DX) {
        DX.viz.charts.series.consts = {
            events: {
                mouseover: 'mouseover',
                mouseout: 'mouseout',
                mousemove: 'mousemove',
                touchstart: 'touchstart',
                touchmove: 'touchmove',
                touchend: 'touchend',
                mousedown: 'mousedown',
                mouseup: 'mouseup',
                click: 'click',
                selectSeries: 'selectseries',
                deselectSeries: 'deselectseries',
                selectPoint: 'selectpoint',
                deselectPoint: 'deselectpoint',
                showPointTooltip: 'showpointtooltip',
                hidePointTooltip: 'hidepointtooltip'
            },
            states: {
                hover: 'hover',
                normal: 'normal',
                selected: 'selected',
                normalMark: 0,
                hoverMark: 1,
                selectedMark: 2
            },
            animations: {
                showDuration: {duration: 400},
                hideGroup: {opacity: 0.0001},
                showGroup: {opacity: 1}
            }
        }
    })(DevExpress);
    /*! Module viz-core, file seriesDrawers.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            utils = utils = DX.utils;
        series.SeriesPointsDrawerMixin = {
            drawPoints: function(group, labelsGroup, points, animationEnabled) {
                var self = this,
                    labelVisible = self.areLabelsVisible();
                if (self.hoverPattern) {
                    self.styles.states.hover.fill = this.hoverPattern.id;
                    self.styles.states.selected.fill = this.selectedPattern.id
                }
                $.each(points, function(i, point) {
                    point.adjustSeriesLabels = self.adjustSeriesLabels;
                    if (!point.isInVisibleArea(point.x, point.y, point.width || 0, point.height || 0))
                        return;
                    point.options.visible && point.drawMarker(self.renderer, group, animationEnabled);
                    labelVisible && point.drawLabel(self.renderer, labelsGroup)
                })
            },
            drawPointTrackers: function(points) {
                var self = this,
                    trackersVisible = !self._suppressTrackers;
                $.each(points, function drawPointTracker(i, point) {
                    if (!point.isInVisibleArea(point.x, point.y, point.width || 0, point.height || 0))
                        return;
                    trackersVisible && point.drawTrackerMarker(self.renderer, self.options.markerTrackerGroup)
                })
            }
        };
        series.LineDrawerMixin = {
            drawLine: function(seriesElementsGroup, segment) {
                this.paths.push(this.createSpecialPath(segment, this.styles.attributes).append(seriesElementsGroup))
            },
            drawLineTracker: function(segment) {
                var self = this,
                    styles = this.styles,
                    strokeWidth;
                if (this._suppressTrackers)
                    return;
                strokeWidth = styles.attributes.strokeWidth < 20 ? 20 : styles.attributes.strokeWidth;
                var tracker = self.createSpecialPath(segment, {
                        strokeWidth: strokeWidth,
                        stroke: 'grey',
                        opacity: 0.0001
                    }).append(self.options.seriesTrackerGroup);
                self.trackerElements.push(tracker);
                tracker.data({series: self})
            },
            createSpecialPath: function(segment, argument) {
                return this.renderer.createPath(segment, argument)
            }
        };
        series.AreaDrawerMixin = {
            drawArea: function(seriesElementsGroup, index, areaSegment) {
                this.resetLineColors();
                if (this.isStackedSeries() || this.isFullStackedSeries())
                    this.seriesGroup.toBackground();
                if (this.segments[index].length === 1) {
                    var stickArea = this.renderer.createPath(areaSegment, this.styles.stick).append(seriesElementsGroup);
                    stickArea.stick = true;
                    this.areas.push(stickArea)
                }
                else
                    this.areas.push(this.createSpecialArea(areaSegment, this.styles.area).append(seriesElementsGroup));
                if (this.hoverPattern) {
                    this.styles.area.states.hover.fill = this.hoverPattern.id;
                    this.styles.area.states.selected.fill = this.selectedPattern.id;
                    this.styles.states.hover.fill = 'none';
                    this.styles.states.selected.fill = 'none'
                }
            },
            drawAreaTracker: function(index, segment) {
                var tracker;
                if (this._suppressTrackers)
                    return;
                if (this.areaSegments[index].length === 2)
                    tracker = this.renderer.createPath(this.areaSegments[index], {
                        strokeWidth: 20,
                        stroke: 'grey',
                        opacity: 0.0001
                    }).append(this.options.seriesTrackerGroup);
                else
                    tracker = this.createSpecialArea(this.areaSegments[index], {
                        strokeWidth: 0,
                        fill: 'grey',
                        opacity: 0.0001
                    }).append(this.options.seriesTrackerGroup);
                this.trackerElements.push(tracker);
                tracker.data({series: this})
            },
            prepareSegments: function(index) {
                this.areaSegments = this.areaSegments || [];
                var segments = this.preparedSegments || this.segments,
                    fwPoints = $.map(segments[index], function(pt) {
                        return pt.getCoords()
                    }),
                    bwPoints = $.map(segments[index].slice().reverse(), function(pt) {
                        return pt.getCoords(true)
                    });
                this.areaSegments[index] = fwPoints.concat(bwPoints)
            },
            createSpecialArea: function(segment, attributes) {
                return this.renderer.createArea(segment, attributes)
            }
        };
        series.SplineDrawerMixin = {
            drawSpline: function(seriesElementsGroup, index, segment) {
                series.LineDrawerMixin.drawLine.call(this, seriesElementsGroup, segment)
            },
            drawSplineTracker: function(index) {
                series.LineDrawerMixin.drawLineTracker.call(this, this.preparedSegments[index])
            },
            prepareSegments: function(index) {
                var self = this,
                    bezierPoints = [],
                    pointsCopy = self.segments[index];
                self.preparedSegments = self.preparedSegments || [];
                var checkExtr = function(otherPointCoord, pointCoord, controlCoord) {
                        return otherPointCoord > pointCoord && controlCoord > otherPointCoord || otherPointCoord < pointCoord && controlCoord < otherPointCoord ? otherPointCoord : controlCoord
                    };
                var clonePoint = function(point, newX, newY) {
                        var p = utils.clone(point);
                        p.x = newX;
                        p.y = newY;
                        return p
                    };
                if (pointsCopy.length !== 1)
                    $.each(pointsCopy, function(i, curPoint) {
                        var leftControlX,
                            leftControlY,
                            rightControlX,
                            rightControlY,
                            prevPoint,
                            nextPoint,
                            xCur,
                            yCur,
                            x1,
                            x2,
                            y1,
                            y2,
                            delta,
                            lambda = 0.5,
                            curIsExtremum,
                            leftPoint,
                            rightPoint,
                            a,
                            b,
                            c,
                            xc,
                            yc,
                            shift;
                        if (!i) {
                            bezierPoints.push(curPoint);
                            bezierPoints.push(curPoint);
                            return
                        }
                        prevPoint = pointsCopy[i - 1];
                        if (i < pointsCopy.length - 1) {
                            nextPoint = pointsCopy[i + 1];
                            xCur = curPoint.x;
                            yCur = curPoint.y;
                            x1 = prevPoint.x;
                            x2 = nextPoint.x;
                            y1 = prevPoint.y;
                            y2 = nextPoint.y;
                            curIsExtremum = !!(!self.options.rotated && (yCur <= prevPoint.y && yCur <= nextPoint.y || yCur >= prevPoint.y && yCur >= nextPoint.y) || self.options.rotated && (xCur <= prevPoint.x && xCur <= nextPoint.x || xCur >= prevPoint.x && xCur >= nextPoint.x));
                            if (curIsExtremum)
                                if (!self.options.rotated) {
                                    rightControlY = leftControlY = yCur;
                                    rightControlX = (xCur + nextPoint.x) / 2;
                                    leftControlX = (xCur + prevPoint.x) / 2
                                }
                                else {
                                    rightControlX = leftControlX = xCur;
                                    rightControlY = (yCur + nextPoint.y) / 2;
                                    leftControlY = (yCur + prevPoint.y) / 2
                                }
                            else {
                                a = y2 - y1;
                                b = x1 - x2;
                                c = y1 * x2 - x1 * y2;
                                if (!self.options.rotated) {
                                    xc = xCur;
                                    yc = -1 * (a * xc + c) / b;
                                    shift = yc - yCur || 0;
                                    y1 -= shift;
                                    y2 -= shift
                                }
                                else {
                                    yc = yCur;
                                    xc = -1 * (b * yc + c) / a;
                                    shift = xc - xCur || 0;
                                    x1 -= shift;
                                    x2 -= shift
                                }
                                rightControlX = (xCur + lambda * x2) / (1 + lambda);
                                rightControlY = (yCur + lambda * y2) / (1 + lambda);
                                leftControlX = (xCur + lambda * x1) / (1 + lambda);
                                leftControlY = (yCur + lambda * y1) / (1 + lambda)
                            }
                            if (!self.options.rotated) {
                                leftControlY = checkExtr(prevPoint.y, yCur, leftControlY);
                                rightControlY = checkExtr(nextPoint.y, yCur, rightControlY)
                            }
                            else {
                                leftControlX = checkExtr(prevPoint.x, xCur, leftControlX);
                                rightControlX = checkExtr(nextPoint.x, xCur, rightControlX)
                            }
                            leftPoint = clonePoint(curPoint, leftControlX, leftControlY);
                            rightPoint = clonePoint(curPoint, rightControlX, rightControlY);
                            bezierPoints.push(leftPoint, curPoint, rightPoint)
                        }
                        else {
                            bezierPoints.push(curPoint, curPoint);
                            return
                        }
                    });
                else
                    bezierPoints.push(pointsCopy[0]);
                self.preparedSegments[index] = bezierPoints
            },
            createSpecialPath: function(segment, argument) {
                return this.renderer.createBezierPath(segment, argument)
            }
        };
        series.SplineAreaDrawerMixin = {
            drawSplineArea: series.AreaDrawerMixin.drawArea,
            drawSplineAreaTracker: series.AreaDrawerMixin.drawAreaTracker,
            prepareSegments: function(index) {
                series.SplineDrawerMixin.prepareSegments.call(this, index);
                series.AreaDrawerMixin.prepareSegments.call(this, index);
                var segment = this.areaSegments[index];
                var lastFwPoint = segment[segment.length / 2 - 1];
                var firstBwPoint = segment[segment.length / 2];
                segment.splice(segment.length / 2, 0, {
                    x: lastFwPoint.x,
                    y: lastFwPoint.y
                }, {
                    x: firstBwPoint.x,
                    y: firstBwPoint.y
                })
            },
            createSpecialArea: function(segment, attributes) {
                return this.renderer.createBezierArea(segment, attributes)
            }
        };
        series.StepLineDrawerMixin = {
            drawStepLine: function(seriesElementsGroup, index, segment) {
                series.LineDrawerMixin.drawLine.call(this, seriesElementsGroup, segment)
            },
            drawStepLineTracker: function(index, segment) {
                series.LineDrawerMixin.drawLineTracker.call(this, this.preparedSegments[index])
            },
            prepareSegments: function(index) {
                var self = this,
                    segmentPoint = [];
                self.preparedSegments = self.preparedSegments || [];
                $.each(self.segments[index], function(i, pt) {
                    var stepY;
                    if (!i) {
                        segmentPoint.push(pt);
                        return
                    }
                    stepY = segmentPoint[segmentPoint.length - 1].y;
                    if (stepY !== pt.y) {
                        var point = utils.clone(pt);
                        point.y = stepY;
                        segmentPoint.push(point)
                    }
                    segmentPoint.push(pt)
                });
                self.preparedSegments[index] = segmentPoint
            },
            createSpecialPath: function(segment, argument) {
                return this.renderer.createPath(segment, argument)
            }
        };
        series.StepAreaDrawerMixin = {
            drawStepArea: series.AreaDrawerMixin.drawArea,
            drawStepAreaTrackers: series.AreaDrawerMixin.drawAreaTracker,
            prepareSegments: function(index) {
                series.StepLineDrawerMixin.prepareSegments.call(this, index);
                series.AreaDrawerMixin.prepareSegments.call(this, index)
            },
            createSpecialArea: function(segment, attributes) {
                return this.renderer.createArea(segment, attributes)
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file seriesStatesVisualizer.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            ALL_SERIES_POINTS_MODE = 'allseriespoints',
            INCLUDE_POINTS_MODE = 'includepoints',
            statesConsts = series.consts.states;
        series.pointVisualizationMixin = {
            applyPointStyle: function(mode, nameFunc) {
                if (mode === ALL_SERIES_POINTS_MODE || mode === INCLUDE_POINTS_MODE)
                    $.each(this.segments, function(_, segment) {
                        $.each(segment, function(_, pt) {
                            if (!(pt.fullState & statesConsts.selectedMark))
                                pt[nameFunc]()
                        })
                    })
            },
            applyPointNormalStyle: function(mode) {
                this.applyPointStyle(mode, 'applyNormalStyle')
            },
            applyPointHoverStyle: function(mode) {
                this.applyPointStyle(mode, 'applyHoverStyle')
            },
            applyPointSelectionStyle: function(mode) {
                this.applyPointStyle(mode, 'applySelectionStyle')
            }
        };
        series.pathVisualizationMixin = {
            applyPathStyle: function(style) {
                var self = this;
                $.each(this.paths, function(_, path) {
                    path.applySettings(style)
                })
            },
            applyPathNormalStyle: function() {
                this.applyPathStyle(this.styles.states.normal)
            },
            applyPathHoverStyle: function() {
                this.applyPathStyle(this.styles.states.hover)
            },
            applyPathSelectionStyle: function() {
                this.applyPathStyle(this.styles.states.selected)
            }
        };
        series.areaVisualizationMixin = {
            applyAreaStyle: function(mode, style) {
                var self = this;
                if (this.areas)
                    $.each(this.areas, function(_, area) {
                        if (!area.stick)
                            area.applySettings(self.styles.area.states[style]);
                        else
                            area.applySettings(self.styles.stick.states[style])
                    })
            },
            applyAreaNormalStyle: function(mode) {
                this.applyAreaStyle(mode, 'normal')
            },
            applyAreaHoverStyle: function(mode) {
                this.applyAreaStyle(mode, 'hover')
            },
            applyAreaSelectionStyle: function(mode) {
                this.applyAreaStyle(mode, 'selected')
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file seriesAdjustOptions.js */
    (function($, DX) {
        var series = DX.viz.charts.series;
        series.LineSeriesAdjustOptionsMixin = {adjustOptions: function() {
                var styles = this.styles,
                    attributes = styles.attributes,
                    hover = styles.states.hover,
                    selected = styles.states.selected,
                    normal = styles.states.normal;
                attributes.stroke = attributes.fill;
                attributes.fill = 'none';
                attributes.strokeWidth = attributes.lineWidth;
                normal.stroke = normal.fill;
                normal.fill = 'none';
                normal.strokeWidth = normal.lineWidth;
                hover.stroke = hover.fill;
                hover.fill = 'none';
                hover.strokeWidth = hover.lineWidth;
                selected.stroke = selected.fill;
                selected.fill = 'none';
                selected.strokeWidth = selected.lineWidth
            }};
        series.AreaSeriesAdjustOptionsMixin = {adjustOptions: function() {
                var styles = this.styles,
                    attributes = styles.attributes,
                    states = styles.states,
                    hover = states.hover,
                    selected = states.selected,
                    normal = states.normal,
                    areaNormal = {},
                    areaHover = {},
                    areaSelected = {},
                    stickNormal = {},
                    stickHover = {},
                    stickSelected = {},
                    opacity;
                opacity = 'opacity' in attributes ? attributes.opacity : 0.5;
                areaNormal = {
                    fill: normal.fill,
                    stroke: 'none',
                    strokeWidth: 0,
                    opacity: opacity
                };
                areaHover = {
                    fill: hover.fill,
                    stroke: 'none',
                    strokeWidth: 0,
                    opacity: opacity
                };
                areaSelected = {
                    fill: selected.fill,
                    stroke: 'none',
                    strokeWidth: 0,
                    opacity: opacity
                };
                stickNormal = {
                    fill: 'none',
                    stroke: normal.fill,
                    strokeWidth: 1,
                    opacity: opacity
                };
                stickHover = {
                    fill: 'none',
                    stroke: hover.fill,
                    strokeWidth: 1,
                    opacity: opacity
                };
                stickSelected = {
                    fill: 'none',
                    stroke: selected.fill,
                    strokeWidth: 1,
                    opacity: opacity
                };
                styles.area = {
                    'class': 'dxc-area-element',
                    fill: attributes.fill,
                    stroke: 'none',
                    strokeWidth: 0,
                    opacity: opacity,
                    states: {
                        normal: areaNormal,
                        hover: areaHover,
                        selected: areaSelected
                    }
                };
                styles.stick = {
                    'class': 'dxc-area-element',
                    fill: 'none',
                    stroke: attributes.fill,
                    strokeWidth: 1,
                    opacity: opacity,
                    states: {
                        normal: stickNormal,
                        hover: stickHover,
                        selected: stickSelected
                    }
                }
            }};
        series.BarSeriesAdjustOptionsMixin = {adjustOptions: function() {
                var styles = this.styles,
                    options = this.options,
                    attributes = styles.attributes,
                    hover = styles.states.hover,
                    selected = styles.states.selected,
                    normal = styles.states.normal,
                    pointAttributes = styles.point.attributes,
                    pointHover = styles.point.states.hover,
                    pointSelected = styles.point.states.selected,
                    pointNormal = styles.point.states.normal,
                    hoverMode = options.hoverMode,
                    selectionMode = options.selectionMode,
                    func = function(mode) {
                        if (!mode)
                            return false;
                        switch (mode.toLowerCase()) {
                            case"allseriespoints":
                            case"allargumentpoints":
                            case"none":
                                return true
                        }
                    };
                $.extend(true, pointAttributes, attributes);
                $.extend(true, pointHover, hover);
                $.extend(true, pointSelected, selected);
                $.extend(true, pointNormal, normal);
                pointHover.r = pointSelected.r = pointNormal.r = pointAttributes.r;
                styles.point.hoverMode = func(hoverMode) && hoverMode;
                styles.point.selectionMode = func(selectionMode) && selectionMode;
                styles.point.visible = true
            }};
        series.CandleStickSeriesAdjustOptionsMixin = {adjustOptions: function() {
                var styles = this.styles,
                    options = this.options,
                    attributes = styles.attributes,
                    hover = styles.states.hover,
                    selected = styles.states.selected,
                    normal = styles.states.normal,
                    pointAttributes = styles.point.attributes,
                    pointHover = styles.point.states.hover,
                    pointSelected = styles.point.states.selected,
                    pointNormal = styles.point.states.normal,
                    hoverMode = options.hoverMode,
                    selectionMode = options.selectionMode,
                    func = function(mode) {
                        if (!mode)
                            return false;
                        switch (mode.toLowerCase()) {
                            case"allseriespoints":
                            case"allargumentpoints":
                            case"none":
                                return true
                        }
                    };
                attributes.stroke = attributes.fill;
                attributes.strokeWidth = attributes.lineWidth;
                normal.stroke = normal.fill;
                normal.strokeWidth = normal.lineWidth;
                hover.stroke = hover.fill;
                hover.strokeWidth = hover.lineWidth;
                selected.stroke = selected.fill;
                selected.strokeWidth = selected.lineWidth;
                $.extend(true, pointAttributes, attributes);
                $.extend(true, pointHover, hover);
                $.extend(true, pointSelected, selected);
                $.extend(true, pointNormal, normal);
                pointHover.r = pointSelected.r = pointNormal.r = pointAttributes.r = 0;
                styles.point.hoverMode = func(hoverMode) && hoverMode;
                styles.point.selectionMode = func(selectionMode) && selectionMode;
                styles.point.visible = true
            }};
        series.BubleSeriesAdjustOptionsMixin = {adjustOptions: function() {
                var styles = this.styles,
                    options = this.options,
                    attributes = styles.attributes,
                    hover = styles.states.hover,
                    selected = styles.states.selected,
                    normal = styles.states.normal,
                    pointAttributes = styles.point.attributes,
                    pointHover = styles.point.states.hover,
                    pointSelected = styles.point.states.selected,
                    pointNormal = styles.point.states.normal,
                    hoverMode = options.hoverMode,
                    selectionMode = options.selectionMode,
                    func = function(mode) {
                        if (!mode)
                            return false;
                        switch (mode.toLowerCase()) {
                            case"allseriespoints":
                            case"allargumentpoints":
                            case"none":
                                return true
                        }
                    };
                $.extend(true, pointAttributes, attributes);
                $.extend(true, pointHover, hover);
                $.extend(true, pointSelected, selected);
                $.extend(true, pointNormal, normal);
                delete pointHover.r;
                delete pointSelected.r;
                delete pointNormal.r;
                styles.point.hoverMode = func(hoverMode) && hoverMode;
                styles.point.selectionMode = func(selectionMode) && selectionMode;
                styles.point.visible = true
            }}
    })(jQuery, DevExpress);
    /*! Module viz-core, file seriesAnimation.js */
    (function($, DX, undefined) {
        var series = DX.viz.charts.series;
        series.pointsAnimation = {
            animatePoints: function(complete) {
                if (this.points && this.points.length) {
                    var lastPointIndex = this.points.length - 1;
                    $.each(this.points, function(index, pt) {
                        pt.animate(index === lastPointIndex ? complete : undefined)
                    })
                }
                else
                    complete && complete()
            },
            sequentialAnimatePoints: function(complete) {
                if (this.styles && this.styles.point.visible && this.segments) {
                    var _this = this,
                        i = 0,
                        t = 0.2,
                        pointsCount = _this.points && _this.points.length,
                        duration = 1 / (t * (pointsCount - 1) + 1);
                    var animateP = function() {
                            if (_this.points[i])
                                _this.points[i++].animate(i === pointsCount ? complete : undefined, duration, function(_, p) {
                                    if (p >= t) {
                                        this.step = null;
                                        animateP()
                                    }
                                })
                        };
                    animateP()
                }
            }
        };
        series.pathAnimation = {
            animatePaths: function(complete) {
                var self = this,
                    segments = self.preparedSegments || self.segments;
                if (segments && segments.length && self.paths && self.paths.length)
                    $.each(self.paths, function(i, path) {
                        path.animate({points: segments[i]}, {}, i == segments.length - 1 ? complete : undefined)
                    });
                else
                    complete && complete()
            },
            getZeroPathPoints: function(i) {
                var segments = this.preparedSegments || this.segments;
                return $.map(segments[i], function(pt) {
                        return pt.getDefaultCoords()
                    })
            }
        };
        series.areaAnimation = {
            animateAreas: function(complete) {
                var self = this,
                    lastAreaIndex;
                if (self.areaSegments && self.areaSegments.length && self.areas) {
                    lastAreaIndex = self.areas.length - 1;
                    $.each(self.areas, function(i, area) {
                        area.animate({points: self.areaSegments[i]}, undefined, i === lastAreaIndex ? complete : undefined)
                    })
                }
                else
                    complete && complete()
            },
            getZeroAreaPoints: function(i) {
                var fwPoints,
                    bwPoints,
                    segments = this.preparedSegments || this.segments;
                fwPoints = $.map(segments[i], function(pt) {
                    return pt.getDefaultCoords()
                });
                bwPoints = $.map(segments[i].slice().reverse(), function(pt) {
                    return pt.getDefaultCoords()
                });
                return fwPoints.concat(bwPoints)
            }
        };
        series.splineAreaAnimation = {
            animateAreas: function(complete) {
                series.areaAnimation.animateAreas.call(this, complete)
            },
            getZeroAreaPoints: function(i) {
                var areaPoints = series.areaAnimation.getZeroAreaPoints.call(this, i);
                var lastFwPoint = areaPoints[areaPoints.length / 2 - 1];
                var firstBwPoint = areaPoints[areaPoints.length / 2];
                areaPoints.splice(areaPoints.length / 2, 0, {
                    x: lastFwPoint.x,
                    y: lastFwPoint.y
                }, {
                    x: firstBwPoint.x,
                    y: firstBwPoint.y
                });
                return areaPoints
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file seriesSpecialMethods.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            isDefined = DX.utils.isDefined,
            utils = DX.utils;
        series.specialAreaMethodsMixin = {resetLineColors: function() {
                var styles = this.styles,
                    attributes = styles.attributes,
                    states = styles.states,
                    hover = states.hover,
                    selected = states.selected,
                    normal = states.normal;
                attributes.fill = 'none';
                delete attributes.lineWidth;
                normal.fill = 'none';
                delete normal.lineWidth;
                hover.fill = 'none';
                delete hover.lineWidth;
                selected.fill = 'none';
                delete selected.lineWidth
            }};
        series.specialBarMethodsMixin = {_getPointSize: function() {
                return 3
            }};
        series.specialCandleStickMethodsMixin = {
            getRangeData: function() {
                var self = this,
                    options = self.options,
                    rotated = options.rotated,
                    valAxis = rotated ? 'X' : 'Y',
                    argAxis = rotated ? 'Y' : 'X',
                    points = self.points,
                    vals = [],
                    args = [];
                var compareNumeric = function(a, b) {
                        return a - b
                    };
                $.each(this.points, function(i, val) {
                    isDefined(val.argument) && args.push(val.argument);
                    if (val.hasValue()) {
                        vals.push(val.highValue);
                        vals.push(val.lowValue)
                    }
                });
                self.rangeData = {};
                var processArgument = function(arg, prevArg) {
                        var interval;
                        if (utils.isDefined(prevArg))
                            interval = Math.abs(arg - prevArg);
                        if (utils.isDefined(interval) && (interval < self.rangeData.intervalX || !utils.isDefined(self.rangeData.intervalX)))
                            self.rangeData.intervalX = interval
                    };
                if (vals.length) {
                    vals.sort(compareNumeric);
                    self.rangeData['max' + valAxis] = vals[vals.length - 1];
                    self.rangeData['min' + valAxis] = vals[0];
                    $.each(points, function(i, point) {
                        var prevPoint,
                            arg = point.argument,
                            prevArg;
                        if (i !== 0) {
                            prevPoint = points[i - 1];
                            prevArg = prevPoint.argument
                        }
                        processArgument(arg, prevArg)
                    })
                }
                if (args.length && options.argumentAxisType !== 'discrete') {
                    args.sort(compareNumeric);
                    self.rangeData['min' + argAxis] = args[0];
                    self.rangeData['max' + argAxis] = args[args.length - 1]
                }
                else
                    self.rangeData['categories' + argAxis] = args;
                return this.rangeData
            },
            _getPointStyles: function(i, reductionLevel, valueFields) {
                var pointStylesReduct = $.extend(true, {}, this.styles.point || {}),
                    innerColor = this.styles.reduction.innerColor,
                    className = 'dx-candle-default',
                    reductionColor = this.styles.reduction.color;
                if (valueFields.open !== null && valueFields.high !== null && valueFields.low !== null && valueFields.close !== null) {
                    if (i !== 0)
                        if (this.prevLevelValue !== null && reductionLevel < this.prevLevelValue) {
                            pointStylesReduct.attributes.fill = pointStylesReduct.states.normal.fill = pointStylesReduct.states.hover.fill = pointStylesReduct.states.selected.fill = reductionColor;
                            pointStylesReduct.attributes.stroke = pointStylesReduct.states.normal.stroke = pointStylesReduct.states.hover.stroke = pointStylesReduct.states.selected.stroke = reductionColor;
                            className = 'dx-candle-reduction'
                        }
                    this.prevLevelValue = reductionLevel;
                    if (valueFields.open < valueFields.close) {
                        pointStylesReduct.attributes.fill = pointStylesReduct.states.normal.fill = pointStylesReduct.states.hover.fill = pointStylesReduct.states.selected.fill = innerColor;
                        className = (className ? className : '') + ' dx-candle-positive'
                    }
                }
                pointStylesReduct.attributes['class'] = className;
                return {
                        className: className,
                        pointStylesReduct: pointStylesReduct
                    }
            },
            reinitData: function(data) {
                var self = this,
                    level,
                    pointFactory = series.pointFactory,
                    argumentField = this.options.argumentField || 'date',
                    openValueField = this.options.openValueField || 'open',
                    highValueField = this.options.highValueField || 'high',
                    lowValueField = this.options.lowValueField || 'low',
                    closeValueField = this.options.closeValueField || 'close',
                    tagField = this.options.tagField,
                    styles;
                this.segments = [];
                if (!data.length) {
                    this.points = [];
                    return
                }
                self.level = this.styles.reduction.level;
                switch ((self.level || '').toLowerCase()) {
                    case'open':
                        level = openValueField;
                        break;
                    case'high':
                        level = highValueField;
                        break;
                    case'low':
                        level = lowValueField;
                        break;
                    default:
                        level = closeValueField;
                        self.level = 'close';
                        break
                }
                self.pointsByArgument = {};
                self.className = 'dx-candle-default';
                this.points = $.map(data, function(val, i) {
                    var point;
                    if (val[argumentField] === undefined || val[argumentField] === null || val[openValueField] === undefined || val[highValueField] === undefined || val[lowValueField] === undefined || val[closeValueField] === undefined)
                        return;
                    styles = self._getPointStyles(i, val[level], {
                        open: val[openValueField],
                        high: val[highValueField],
                        close: val[closeValueField],
                        low: val[lowValueField]
                    });
                    point = pointFactory.createPoint(self.type, {
                        openValue: val[openValueField],
                        pointClassName: styles.className,
                        highValue: val[highValueField],
                        lowValue: val[lowValueField],
                        closeValue: val[closeValueField],
                        argument: val[argumentField],
                        originalOpenValue: val['original' + openValueField],
                        originalHighValue: val['original' + highValueField],
                        originalLowValue: val['original' + lowValueField],
                        originalCloseValue: val['original' + closeValueField],
                        originalArgument: val['original' + argumentField],
                        options: styles.pointStylesReduct,
                        tag: val[tagField],
                        reductionValue: val[level],
                        series: self
                    });
                    self.pointsByArgument[point.argument.valueOf()] = self.pointsByArgument[point.argument.valueOf()] || point;
                    return point
                });
                delete this.prevLevelValue;
                self.originalPoints = self.points;
                this._segmentPoints()
            },
            createPatterns: function() {
                var self = this,
                    hover = self.styles.states.hover,
                    selected = self.styles.states.selected,
                    normal = self.styles.states.normal,
                    reductionColor = self.styles.reduction.color,
                    renderer = self.renderer;
                self.callBase();
                if (!self.patternColorReduction)
                    self.patternColorReduction = reductionColor;
                if (!self.hoverPatternReduction) {
                    self.hoverPatternReduction = renderer.createPattern(normal.fill === hover.fill ? self.patternColorReduction : hover.fill, hover.hatching);
                    self.selectedPatternReduction = renderer.createPattern(normal.fill === selected.fill ? self.patternColorReduction : selected.fill, selected.hatching)
                }
                self.hoverPatternReduction.append();
                self.selectedPatternReduction.append()
            },
            createMarkerGroups: function(seriesMarkersGroup) {
                var styles = this.styles,
                    reduction = styles.reduction,
                    defaultMarkersOptions = $.extend({'class': 'default-markers'}, styles.point.states.normal),
                    reductionMarkersOptions = $.extend({'class': 'reduction-markers'}, styles.point.states.normal, {
                        fill: reduction.color,
                        stroke: reduction.color
                    }),
                    defaultPositiveMarkersOptions = $.extend({'class': 'default-positive-markers'}, styles.point.states.normal, {fill: reduction.innerColor}),
                    reductionPositiveMarkersOptions = $.extend({'class': 'reduction-positive-markers'}, styles.point.states.normal, {
                        fill: reduction.innerColor,
                        stroke: reduction.color
                    });
                return {
                        defaultMarkersGroup: this.renderer.createGroup(defaultMarkersOptions).append(seriesMarkersGroup),
                        reductionMarkersGroup: this.renderer.createGroup(reductionMarkersOptions).append(seriesMarkersGroup),
                        defaultPositiveMarkersGroup: this.renderer.createGroup(defaultPositiveMarkersOptions).append(seriesMarkersGroup),
                        reductionPositiveMarkersGroup: this.renderer.createGroup(reductionPositiveMarkersOptions).append(seriesMarkersGroup)
                    }
            },
            getValueFields: function() {
                return [this.options.openValueField, this.options.highValueField, this.options.lowValueField, this.options.closeValueField]
            },
            updateTeamplateFieldNames: function() {
                var _this = this;
                _this.options.openValueField = _this.options.openValueField + _this.name;
                _this.options.highValueField = _this.options.highValueField + _this.name;
                _this.options.lowValueField = _this.options.lowValueField + _this.name;
                _this.options.closeValueField = _this.options.closeValueField + _this.name;
                _this.options.tagField = _this.options.tagField + _this.name
            },
            _getPointSize: function() {
                return 10
            }
        };
        series.specialPieMethodsMixin = {
            arrangePoints: function() {
                var series = this,
                    minSegmentSize = series.styles.minSegmentSize,
                    points,
                    pointsLength,
                    correction = 0,
                    translator = this.translator,
                    total = 0,
                    percent,
                    i,
                    totalNotMinValues = 0,
                    totalMinSegmentSize = 0,
                    minShownValue,
                    isClockWise = series.options.segmentsDirection !== 'anticlockwise';
                series.points = $.map(series.points, function(point) {
                    if (point.value === null || point.value < 0 || point.value === 0 && !minSegmentSize)
                        return null;
                    return point
                });
                points = series.points;
                pointsLength = points.length;
                for (i = 0; i < pointsLength; i++)
                    total += points[i].value;
                if (total === 0) {
                    total = pointsLength;
                    $.each(series.points, function(i, point) {
                        point.value = 1
                    })
                }
                if (minSegmentSize) {
                    $.each(points, function(i, point) {
                        if (point.value < minSegmentSize * total / 360)
                            totalMinSegmentSize += minSegmentSize;
                        else
                            totalNotMinValues += point.value
                    });
                    minShownValue = totalMinSegmentSize < 360 ? minSegmentSize * totalNotMinValues / (360 - totalMinSegmentSize) : 0
                }
                $.each(isClockWise ? points : points.concat([]).reverse(), function(i, point) {
                    var val = point.value,
                        updatedZeroValue;
                    if (minSegmentSize && val < minShownValue) {
                        updatedZeroValue = minShownValue;
                        point.value = updatedZeroValue
                    }
                    percent = val / total;
                    point.correctValue(correction, percent);
                    correction = correction + (updatedZeroValue || val)
                })
            },
            correctPosition: function(correction) {
                var debug = DX.utils.debug;
                debug.assert(correction, 'correction was not passed');
                debug.assertParam(correction.centerX, 'correction.centerX was not passed');
                debug.assertParam(correction.centerY, 'correction.centerY was not passed');
                debug.assertParam(correction.radiusInner, 'correction.radiusInner was not passed');
                debug.assertParam(correction.radiusOuter, 'correction.radiusOuter was not passed');
                $.each(this.points, function(_, point) {
                    point.correctPosition(correction)
                })
            },
            getRangeData: function() {
                var range = this.callBase();
                if (!range)
                    return range;
                if (range.minY !== undefined) {
                    range.minY = range.minY > 0 ? 0 : range.minY;
                    range.maxY = range.maxY < 0 ? 0 : range.maxY
                }
                return range
            },
            parseStyleOptions: function(options) {
                if (options.label && options.label.position && options.label.position !== 'outside' && options.label.position !== 'inside' && options.label.position !== 'columns')
                    options.label.position = 'outside';
                if (options.label.position && options.label.position === 'columns')
                    options.label.connector.visible = true;
                this.options.segmentsDirection = options.segmentsDirection || 'clockwise';
                this.styles = this.callBase(options);
                this.adjustOptions();
                return this.styles
            }
        };
        series.specialBubbleMethodsMixin = {
            reinitData: function(data) {
                var self = this,
                    createPoint = series.pointFactory.createPoint,
                    rotated = self.options.rotated,
                    pointStyles = self.styles.point,
                    i,
                    curPoint,
                    point,
                    options = self.options,
                    argumentField = options.argumentField,
                    valueField = options.valueField,
                    sizeField = options.sizeField,
                    tagField = options.tagField;
                if (data && data.length)
                    this._canRenderCompleteHandle = true;
                self.points = [];
                self.pointsByArgument = {};
                self.segments = [];
                for (i = 0; i < data.length; i++) {
                    curPoint = data[i];
                    if (!utils.isDefined(curPoint[valueField]) || !utils.isDefined(curPoint[argumentField]) || !utils.isDefined(curPoint[sizeField]))
                        continue;
                    point = createPoint(self.type, {
                        value: curPoint[valueField],
                        argument: curPoint[argumentField],
                        size: curPoint[sizeField],
                        originalValue: curPoint['original' + valueField],
                        originalArgument: curPoint['original' + argumentField],
                        rotated: rotated,
                        options: pointStyles,
                        tag: curPoint[tagField],
                        series: self
                    });
                    self.points.push(point);
                    self.pointsByArgument[point.argument.valueOf()] = self.pointsByArgument[point.argument.valueOf()] || point
                }
                self.originalPoints = self.points;
                self._segmentPoints()
            },
            getValueFields: function() {
                return [this.options.valueField, this.options.sizeField]
            },
            updateTeamplateFieldNames: function() {
                var _this = this;
                _this.options.valueField = _this.options.valueField + _this.name;
                _this.options.sizeField = _this.options.sizeField + _this.name;
                _this.options.tagField = _this.options.tagField + _this.name
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file commonSeriesResampler.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            utils = DX.utils;
        series.SeriesDataFilterMixin = {
            _fusionPoints: function(fusionPoints, type, tick) {
                var result = this._calcMedianValue(fusionPoints, 'value');
                return series.pointFactory.createPoint(type, {
                        value: result,
                        argument: tick,
                        originalValue: result,
                        originalArgument: tick,
                        rotated: this.options.rotated,
                        options: this.styles.point,
                        tag: null,
                        series: this
                    })
            },
            _calcMedianValue: function(fusionPoints, valueField) {
                var result,
                    allValue;
                allValue = $.map(fusionPoints, function(point) {
                    return point[valueField]
                });
                allValue.sort(function(a, b) {
                    return a - b
                });
                result = allValue[Math.floor(allValue.length / 2)];
                return utils.isDefined(result) ? result : null
            },
            _resample: function(ticks, ticksInterval) {
                var self = this,
                    fusPoints = [],
                    arrayFusPoints,
                    result,
                    nowIndexTicks = 0;
                if (this.options.argumentAxisType === 'discrete' || this.options.valueAxisType === 'discrete') {
                    ticksInterval = this.getOriginalPoints().length / ticks;
                    arrayFusPoints = $.map(this.getOriginalPoints(), function(point, index) {
                        if (Math.floor(nowIndexTicks) === index) {
                            nowIndexTicks += ticksInterval;
                            return point
                        }
                        return null
                    });
                    return arrayFusPoints
                }
                arrayFusPoints = $.map(this.getOriginalPoints(), function(point) {
                    switch (self._isInInterval(point.argument, ticks, nowIndexTicks, ticksInterval)) {
                        case true:
                            fusPoints.push(point);
                            break;
                        case false:
                            return null;
                        case'nextInterval':
                            result = self._fusionPoints(fusPoints, self.type, ticks[nowIndexTicks], nowIndexTicks);
                            while (self._isInInterval(point.argument, ticks, nowIndexTicks, ticksInterval) === 'nextInterval')
                                nowIndexTicks++;
                            fusPoints = [];
                            self._isInInterval(point.argument, ticks, nowIndexTicks, ticksInterval) === true && fusPoints.push(point);
                            if (result)
                                return result
                    }
                });
                fusPoints.length && arrayFusPoints.push(self._fusionPoints(fusPoints, self.type, ticks[nowIndexTicks]));
                delete self.prevLevelValue;
                return arrayFusPoints
            },
            _isInInterval: function(argument, ticks, nowIndexTicks, ticksInterval) {
                var minTick = ticks[nowIndexTicks],
                    maxTick = ticks[nowIndexTicks + 1],
                    sumMinTickTicksInterval;
                ticksInterval = $.isNumeric(ticksInterval) ? ticksInterval : utils.convertDateTickIntervalToMilliseconds(ticksInterval);
                sumMinTickTicksInterval = utils.isDate(minTick) ? new Date(minTick.getTime() + ticksInterval) : minTick + ticksInterval;
                if (argument >= minTick && argument < sumMinTickTicksInterval)
                    return true;
                if (argument < minTick || maxTick === undefined)
                    return false;
                return 'nextInterval'
            }
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file financeSeriesResampler.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            utils = DX.utils,
            seriesDataFilterMixin = series.SeriesDataFilterMixin;
        series.FinancialSeriesDataResamplerMixin = {
            _fusionPoints: function(fusionPoints, type, tick, nowIndexTicks) {
                var fusedPoint = utils.clone(fusionPoints[0]),
                    styles,
                    reductionLevel,
                    highValue = -Infinity,
                    lowValue = +Infinity,
                    openValue,
                    closeValue;
                if (!fusionPoints.length)
                    return;
                $.each(fusionPoints, function(_, point) {
                    if (!point.hasValue())
                        return;
                    highValue = Math.max(highValue, point.highValue);
                    lowValue = Math.min(lowValue, point.lowValue);
                    openValue = openValue !== undefined ? openValue : point.openValue;
                    closeValue = point.closeValue !== undefined ? point.closeValue : closeValue
                });
                fusedPoint.argument = tick;
                fusedPoint.openValue = openValue;
                fusedPoint.closeValue = closeValue;
                fusedPoint.highValue = highValue;
                fusedPoint.lowValue = lowValue;
                switch ((this.level || '').toLowerCase()) {
                    case'open':
                        reductionLevel = openValue;
                        break;
                    case'high':
                        reductionLevel = highValue;
                        break;
                    case'low':
                        reductionLevel = lowValue;
                        break;
                    default:
                        reductionLevel = closeValue;
                        break
                }
                styles = this._getPointStyles(nowIndexTicks, reductionLevel, {
                    open: openValue,
                    close: closeValue,
                    high: highValue,
                    low: lowValue
                });
                fusedPoint.pointClassName = styles.className;
                fusedPoint.options = styles.pointStylesReduct;
                fusedPoint.reductionValue = reductionLevel;
                return series.pointFactory.createPoint(type, fusedPoint)
            },
            _resample: seriesDataFilterMixin._resample,
            _isInInterval: seriesDataFilterMixin._isInInterval
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangeSeriesResampler.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            utils = DX.utils,
            seriesDataFilterMixin = series.SeriesDataFilterMixin;
        series.RangeSeriesDataFilterMixin = {
            _fusionPoints: function(fusionPoints, type, tick) {
                var value = series.SeriesDataFilterMixin._calcMedianValue(fusionPoints, 'value'),
                    minValue = series.SeriesDataFilterMixin._calcMedianValue(fusionPoints, 'minValue');
                if (value === null || minValue === null)
                    value = minValue = null;
                return series.pointFactory.createPoint(type, {
                        minValue: minValue,
                        value: value,
                        argument: tick,
                        originalMinValue: minValue,
                        originalValue: value,
                        originalArgument: tick,
                        rotated: this.options.rotated,
                        options: this.styles.point,
                        tag: null,
                        series: this
                    })
            },
            _resample: seriesDataFilterMixin._resample,
            _isInInterval: seriesDataFilterMixin._isInInterval
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file bubbleSeriesResampler.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            seriesDataFilterMixin = series.SeriesDataFilterMixin,
            VALUE = 'value',
            SIZE = 'size';
        series.BubbleSeriesDataResamplerMixin = {
            _fusionPoints: function(fusionPoints, type, tick) {
                var medianValue = this._calcMedianValue(fusionPoints, VALUE),
                    medianSize = this._calcMedianValue(fusionPoints, SIZE);
                return series.pointFactory.createPoint(type, {
                        size: medianSize,
                        value: medianValue,
                        argument: tick,
                        originalValue: medianValue,
                        originalArgument: tick,
                        rotated: this.options.rotated,
                        options: this.styles.point,
                        tag: null,
                        series: this
                    })
            },
            _resample: seriesDataFilterMixin._resample,
            _isInInterval: seriesDataFilterMixin._isInInterval,
            _calcMedianValue: seriesDataFilterMixin._calcMedianValue
        }
    })(jQuery, DevExpress);
    /*! Module viz-core, file basePoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            eventsConsts = series.consts.events,
            statesConsts = series.consts.states,
            utils = DX.utils,
            formatHelper = DX.formatHelper,
            CANVAS_POSITION_DEFAULT = 'canvas_position_default';
        series.BasePoint = DX.Class.inherit({
            ctor: function(data) {
                var debug = DX.utils.debug;
                debug.assertParam(data, 'data was not passed');
                debug.assertParam(data.options, 'options were not passed');
                this.LABEL_BACKGROUND_PADDING_X = 8;
                this.LABEL_BACKGROUND_PADDING_Y = 4;
                this.LABEL_OFFSET = 10;
                this.rotated = !!data.rotated;
                if (data.options.label && data.options.label.position && data.options.label.position !== 'outside' && data.options.label.position !== 'inside')
                    data.options.label.position = 'outside';
                this.options = data.options;
                this.series = data.series;
                this.value = this.initialValue = data.value;
                this.argument = this.initialArgument = data.argument;
                this.originalValue = data.originalValue;
                this.originalArgument = data.originalArgument;
                this.minValue = CANVAS_POSITION_DEFAULT;
                this.labelFormatObject = {
                    argument: this.initialArgument,
                    value: this.initialValue,
                    seriesName: this.series.name,
                    originalValue: this.originalValue,
                    originalArgument: this.originalArgument
                };
                this.tag = data.tag;
                this.pointClassName = data.pointClassName || ''
            },
            dispose: function() {
                var _this = this;
                _this.off();
                _this.trackerGraphic && _this.trackerGraphic.removeData();
                _this.graphic = null;
                _this.trackerGraphic = null;
                _this.hoverPattern = null;
                _this.selectedPattern = null;
                _this.label = null;
                _this.labelBackground = null;
                _this.connector = null;
                _this.insideLabelGroup = null;
                _this.labelGroup = null;
                _this.points = null;
                _this.translator = null;
                _this.options = null;
                _this.series = null;
                _this.tag = null;
                _this.labelFormatObject = null;
                _this.stackPoints = null
            },
            formatLabel: function(options) {
                this.valueText = formatHelper.format(this.value, options.format, options.precision);
                this.argumentText = formatHelper.format(this.argument, options.argumentFormat, options.argumentPrecision);
                if (this.percent !== undefined)
                    this.percentText = formatHelper.format(this.percent, 'percent', options.percentPrecision);
                if (this.total !== undefined)
                    this.totalText = formatHelper.format(this.total, options.format, options.precision);
                return options.customizeText ? options.customizeText.call(this, this) : this.valueText
            },
            setOptions: function(options) {
                this.options = options
            },
            translate: function(translator) {
                this.translator = translator = translator || this.translator;
                if (!this.translator || !this.hasValue())
                    return;
                if (!this.rotated) {
                    this.y = translator.translateY(this.value);
                    this.minY = translator.translateY(this.minValue);
                    this.x = translator.translateX(this.argument);
                    this.defaultY = translator.translateY(CANVAS_POSITION_DEFAULT)
                }
                else {
                    this.y = translator.translateY(this.argument);
                    this.x = translator.translateX(this.value);
                    this.minX = translator.translateX(this.minValue);
                    this.defaultX = translator.translateX(CANVAS_POSITION_DEFAULT)
                }
                this._calculateVisibility(this.x, this.y, 0, 0);
                this.prepareStatesOptions()
            },
            _calculateVisibility: function(x, y, width, height) {
                var visibleArea;
                if (this.translator && this.translator.getCanvasVisibleArea) {
                    visibleArea = this.translator.getCanvasVisibleArea() || {};
                    if (visibleArea.minX > x + (width || 0) || visibleArea.maxX < x || visibleArea.minY > y + (height || 0) || visibleArea.maxY < y)
                        this.visible = false;
                    else
                        this.visible = true
                }
            },
            correctValue: function(correction) {
                this.value += correction;
                if (!utils.isNumber(this.minValue))
                    this.minValue = correction;
                else
                    this.minValue += correction;
                this.translate()
            },
            setPercentValue: function(total, fullStacked) {
                var valuePercent = this.value / total || 0,
                    minValuePercent;
                if (utils.isNumber(this.minValue)) {
                    minValuePercent = this.minValue / total || 0;
                    this.labelFormatObject.percent = valuePercent - minValuePercent
                }
                else
                    this.labelFormatObject.percent = valuePercent;
                this.labelFormatObject.total = total;
                if (fullStacked) {
                    this.value = valuePercent;
                    this.minValue = !minValuePercent ? this.minValue : minValuePercent;
                    this.translate()
                }
            },
            getCoords: function(min) {
                if (!min)
                    return {
                            x: this.x,
                            y: this.y
                        };
                if (!this.rotated)
                    return {
                            x: this.x,
                            y: this.minY
                        };
                return {
                        x: this.minX,
                        y: this.y
                    }
            },
            getDefaultCoords: function() {
                return !this.rotated ? {
                        x: this.x,
                        y: this.defaultY
                    } : {
                        x: this.defaultX,
                        y: this.y
                    }
            },
            getTooltipCoords: function() {
                if (this.graphic)
                    return {
                            x: this.x,
                            y: this.y,
                            offset: this.graphic.getBBox().height / 2
                        };
                else
                    return {
                            x: this.x,
                            y: this.y,
                            offset: 0
                        }
            },
            isInVisibleArea: function() {
                return this.visible
            },
            drawMarker: function(renderer, group, animationEnabled) {
                if (!this.hasValue())
                    return;
                var radius = this.options.attributes.r,
                    states = this.options.states.normal,
                    imageMarker = this.options.image,
                    marker,
                    bbox,
                    markerUrl,
                    markerWidth,
                    markerHeight,
                    markerOffsetX,
                    markerOffsetY,
                    DEFAULT_MARKER_WIDTH = 20,
                    DEFAULT_MARKER_HEIGHT = 20,
                    translateX,
                    translateY,
                    pointAttributes;
                if (animationEnabled)
                    if (this.rotated)
                        translateX = this.defaultX - this.x;
                    else
                        translateY = this.defaultY - this.y;
                pointAttributes = $.extend({
                    translateX: translateX,
                    translateY: translateY
                }, this.options.attributes);
                if (imageMarker) {
                    markerUrl = imageMarker.url ? imageMarker.url.toString() : imageMarker.toString();
                    markerWidth = imageMarker.width || DEFAULT_MARKER_WIDTH;
                    markerHeight = imageMarker.height || DEFAULT_MARKER_HEIGHT;
                    markerOffsetX = Math.round(markerWidth * 0.5);
                    markerOffsetY = Math.round(markerHeight * 0.5);
                    marker = renderer.createImage(this.x - markerOffsetX, this.y - markerOffsetY, markerWidth, markerHeight, markerUrl, {location: 'center'})
                }
                else
                    switch (this.options.symbol) {
                        case'circle':
                            marker = renderer.createCircle(this.x, this.y, radius, pointAttributes);
                            break;
                        case'square':
                        case'polygon':
                        case'triangle':
                        case'cross':
                            marker = renderer.createArea(this.points, pointAttributes);
                            break
                    }
                marker && marker.move(translateX || 0, translateY || 0).append(group);
                this.graphic = marker;
                this._checkState()
            },
            _checkState: function() {
                if (this.isSelected())
                    this.series.setPointSelectedState(this);
                else if (this.isHovered())
                    this.series.setPointHoverState(this);
                else
                    this.fullState = statesConsts.normalMark
            },
            _trackerAttrs: {
                stroke: 'none',
                fill: 'grey',
                opacity: 0.0001,
                inh: true
            },
            storeTrackerR: function() {
                var navigator = window.navigator,
                    touchSupport = 'ontouchstart' in window || navigator.msPointerEnabled && navigator.msMaxTouchPoints || navigator.pointerEnabled && navigator.maxTouchPoints,
                    minTrackerSize = touchSupport ? 20 : 6;
                this.options.trackerR = this.options.attributes.r < minTrackerSize ? minTrackerSize : this.options.attributes.r;
                return this.options.trackerR
            },
            drawTrackerMarker: function(renderer, trackerGroup) {
                if (!this.hasValue())
                    return;
                this.trackerGraphic = renderer.createCircle(this.x, this.y, this.options.trackerR || this.storeTrackerR(), this._trackerAttrs).append(trackerGroup);
                this.trackerGraphic.data({point: this})
            },
            select: function() {
                this.series.selectPoint(this)
            },
            clearSelection: function() {
                this.series.deselectPoint(this)
            },
            _populatePointShape: function(target, radius) {
                var self = this,
                    floorHalfRadius,
                    ceilHalfRadius;
                if (self.options.symbol === 'square')
                    target.points = [{
                            x: self.x - radius,
                            y: self.y - radius
                        }, {
                            x: self.x + radius,
                            y: self.y - radius
                        }, {
                            x: self.x + radius,
                            y: self.y + radius
                        }, {
                            x: self.x - radius,
                            y: self.y + radius
                        }, {
                            x: self.x - radius,
                            y: self.y - radius
                        }];
                if (self.options.symbol === 'polygon')
                    target.points = [{
                            x: self.x - radius,
                            y: self.y
                        }, {
                            x: self.x,
                            y: self.y - radius
                        }, {
                            x: self.x + radius,
                            y: self.y
                        }, {
                            x: self.x,
                            y: self.y + radius
                        }, {
                            x: self.x - radius,
                            y: self.y
                        }];
                if (self.options.symbol === 'triangle')
                    target.points = [{
                            x: self.x - radius,
                            y: self.y - radius
                        }, {
                            x: self.x + radius,
                            y: self.y - radius
                        }, {
                            x: self.x,
                            y: self.y + radius
                        }, {
                            x: self.x - radius,
                            y: self.y - radius
                        }];
                if (self.options.symbol === 'cross') {
                    floorHalfRadius = Math.floor(radius / 2);
                    ceilHalfRadius = Math.ceil(radius / 2);
                    target.points = [{
                            x: self.x - radius,
                            y: self.y - floorHalfRadius
                        }, {
                            x: self.x - floorHalfRadius,
                            y: self.y - radius
                        }, {
                            x: self.x,
                            y: self.y - ceilHalfRadius
                        }, {
                            x: self.x + floorHalfRadius,
                            y: self.y - radius
                        }, {
                            x: self.x + radius,
                            y: self.y - floorHalfRadius
                        }, {
                            x: self.x + ceilHalfRadius,
                            y: self.y
                        }, {
                            x: self.x + radius,
                            y: self.y + floorHalfRadius
                        }, {
                            x: self.x + floorHalfRadius,
                            y: self.y + radius
                        }, {
                            x: self.x,
                            y: self.y + ceilHalfRadius
                        }, {
                            x: self.x - floorHalfRadius,
                            y: self.y + radius
                        }, {
                            x: self.x - radius,
                            y: self.y + floorHalfRadius
                        }, {
                            x: self.x - ceilHalfRadius,
                            y: self.y
                        }]
                }
            },
            prepareStatesOptions: function() {
                var self = this;
                if (self.options.states && self.options.states.normal)
                    self._populatePointShape(self, self.options.states.normal.r)
            },
            applyNormalStyle: function() {
                if (this.graphic) {
                    this._populatePointShape(this.options.states.normal, this.options.states.normal.r);
                    this.graphic.applySettings(this.options.states.normal)
                }
                return this
            },
            applyHoverStyle: function() {
                if (this.graphic && !this.options.image) {
                    this._populatePointShape(this.options.states.hover, this.options.states.hover.r);
                    this.graphic.applySettings(this.options.states.hover);
                    this.graphic.toForeground();
                    this.graphic.addClass('dx-chart-hovered-point')
                }
                return this
            },
            applySelectionStyle: function() {
                if (this.graphic && !this.options.image) {
                    this._populatePointShape(this.options.states.selected, this.options.states.selected.r);
                    this.graphic.applySettings(this.options.states.selected);
                    this.graphic.toForeground();
                    this.graphic.addClass('dx-chart-selected-point')
                }
                return this
            },
            setHoverState: function() {
                this.series.setPointHoverState(this)
            },
            releaseHoverState: function() {
                this.series.releasePointHoverState(this);
                if (this.graphic) {
                    this.graphic.removeClass('dx-chart-hovered-point');
                    !this.isSelected() && this.graphic.toBackground()
                }
            },
            setSelectedState: function() {
                this.series.setPointSelectedState(this)
            },
            releaseSelectedState: function() {
                this.series.releasePointSelectedState(this);
                if (this.graphic)
                    this.graphic.removeClass('dx-chart-selected-point')
            },
            showTooltip: function() {
                this.series.showPointTooltip(this)
            },
            hideTooltip: function() {
                this.series.hidePointTooltip(this)
            },
            on: function(events, data, handler) {
                $(this).on(events, data, handler);
                return this
            },
            off: function(events) {
                $(this).off(events);
                return this
            },
            isSelected: function() {
                return !!(this.fullState & statesConsts.selectedMark)
            },
            isHovered: function() {
                return !!(this.fullState & statesConsts.hoverMark)
            },
            correctLabel: function() {
                this.correctBackgroundPosition();
                this.rotateLabel();
                this.correctLabelPosition()
            },
            drawLabel: function(renderer, group) {
                if (!this.hasValue())
                    return;
                if (!utils.isDefined(this.labelFormatObject.value))
                    return;
                var labelOptions = this.options.label,
                    labelText = this.formatLabel.call(this.labelFormatObject, labelOptions);
                if (!utils.isDefined(labelText))
                    return;
                this.labelGroup = renderer.createGroup().append(group);
                if (this.options.label.connector && this.options.label.connector.strokeWidth)
                    this.connector = renderer.createPath([], labelOptions.connector).append(this.labelGroup);
                this.insideLabelGroup = renderer.createGroup().append(this.labelGroup);
                labelOptions.background['class'] = this.pointClassName;
                if (labelOptions.background.fill && labelOptions.background.fill !== 'none' || labelOptions.background.strokeWidth && labelOptions.background.stroke && labelOptions.background.stroke !== 'none')
                    this.labelBackground = renderer.createRect(this.x, this.y, 0, 0, 0, labelOptions.background).append(this.insideLabelGroup);
                this.label = renderer.createText(labelText, this.x, this.y, labelOptions.attributes).append(this.insideLabelGroup);
                this.correctLabel();
                this.correctConnectorPosition()
            },
            rotateLabel: function() {
                var bbox = this.insideLabelGroup.getBBox(),
                    labelOptions = this.options.label;
                this.insideLabelGroup.applySettings({
                    x: bbox.x + bbox.width / 2,
                    y: bbox.y + bbox.height / 2,
                    rotate: labelOptions.rotationAngle
                })
            },
            getGraphicSettings: function() {
                return {
                        x: this.graphic.settings.x || 0,
                        y: this.graphic.settings.y || 0,
                        height: this.graphic.settings.height || 0,
                        width: this.graphic.settings.width || 0
                    }
            },
            correctLabelPosition: function() {
                var bbox = this.insideLabelGroup.getBBox(),
                    bboxgraphic = this.graphic ? this.graphic.getBBox() : {
                        x: this.x,
                        y: this.y,
                        height: 0,
                        width: 0
                    },
                    x = 0,
                    y = 0;
                if (bboxgraphic.isEmpty)
                    bboxgraphic = {
                        x: this.x,
                        y: this.y,
                        height: 0,
                        width: 0
                    };
                if (!this.rotated)
                    if (this.initialValue > 0 || this.series.isFullStackedSeries())
                        y += bboxgraphic.y - bbox.y - bbox.height - this.LABEL_OFFSET;
                    else
                        y += bboxgraphic.y + bboxgraphic.height - bbox.y + this.LABEL_OFFSET;
                else {
                    y += bboxgraphic.y - bbox.y - bbox.height / 2 + bboxgraphic.height / 2;
                    if (this.initialValue > 0 || this.series.isFullStackedSeries())
                        x += bboxgraphic.x + bboxgraphic.width - bbox.x + this.LABEL_OFFSET;
                    else
                        x += bboxgraphic.x - bbox.x - bbox.width - this.LABEL_OFFSET
                }
                x += this.options.label.horizontalOffset;
                y += this.options.label.verticalOffset;
                this.checkLabelPosition({
                    x: bbox.x + x,
                    y: bbox.y + y,
                    height: bbox.height,
                    width: bbox.width
                }, x, y)
            },
            checkLabelPosition: function(bbox, x, y) {
                var bboxgraphic = this.graphic ? this.graphic.getBBox() : {
                        x: this.x,
                        y: this.y,
                        height: 0,
                        width: 0
                    },
                    visibleArea = this.translator.getCanvasVisibleArea();
                if (bboxgraphic.isEmpty)
                    bboxgraphic = {
                        x: this.x,
                        y: this.y,
                        height: 0,
                        width: 0
                    };
                if (!this.rotated)
                    if (visibleArea.minX <= bboxgraphic.x + bboxgraphic.width && visibleArea.maxX >= bboxgraphic.x) {
                        if (visibleArea.minX > bbox.x && this.adjustSeriesLabels)
                            x += visibleArea.minX - bbox.x;
                        if (visibleArea.maxX < bbox.x + bbox.width && this.adjustSeriesLabels)
                            x -= bbox.x + bbox.width - visibleArea.maxX;
                        if (visibleArea.minY > bbox.y)
                            y += bboxgraphic.y + bboxgraphic.height - bbox.y + this.LABEL_OFFSET;
                        if (visibleArea.maxY < bbox.y + bbox.height)
                            y -= bbox.y + bbox.height - bboxgraphic.y + this.LABEL_OFFSET
                    }
                if (this.rotated)
                    if (visibleArea.minY <= bboxgraphic.y + bboxgraphic.height && visibleArea.maxY >= bboxgraphic.y) {
                        if (visibleArea.minX > bbox.x)
                            x += bboxgraphic.x + bboxgraphic.width - bbox.x + this.LABEL_OFFSET;
                        if (visibleArea.maxX < bbox.x + bbox.width)
                            x -= bbox.x + bbox.width - bboxgraphic.x + this.LABEL_OFFSET;
                        if (visibleArea.minY > bbox.y && this.adjustSeriesLabels)
                            y += visibleArea.minY - bbox.y;
                        if (visibleArea.maxY < bbox.y + bbox.height && this.adjustSeriesLabels)
                            y -= bbox.y + bbox.height - visibleArea.maxY
                    }
                this.insideLabelGroup.move(~~x, ~~y)
            },
            correctBackgroundPosition: function() {
                if (!this.labelBackground)
                    return;
                var bbox = this.label.getBBox(),
                    x = bbox.x - this.LABEL_BACKGROUND_PADDING_X,
                    y = bbox.y - this.LABEL_BACKGROUND_PADDING_Y,
                    width = bbox.width + 2 * this.LABEL_BACKGROUND_PADDING_X,
                    height = bbox.height + 2 * this.LABEL_BACKGROUND_PADDING_Y;
                this.labelBackground.applySettings({
                    x: x,
                    y: y,
                    width: width,
                    height: height
                })
            },
            correctConnectorPosition: function(bboxgraphic) {
                var bbox = this.insideLabelGroup.getBBox(),
                    bboxgraphic = bboxgraphic || (this.graphic ? this.graphic.getBBox() : {
                        x: this.x,
                        y: this.y,
                        height: 0,
                        width: 0
                    }),
                    x1,
                    x2,
                    y1,
                    y2,
                    centerLabelY,
                    centerLabelX;
                if (!this.connector)
                    return;
                if (bboxgraphic.isEmpty)
                    bboxgraphic = {
                        x: this.x,
                        y: this.y,
                        height: 0,
                        width: 0
                    };
                bbox.x = bbox.x + (this.insideLabelGroup.settings.translateX || 0);
                bbox.y = bbox.y + (this.insideLabelGroup.settings.translateY || 0);
                centerLabelY = this.labelBackground ? bbox.y + bbox.height / 2 : null;
                centerLabelX = this.labelBackground ? bbox.x + bbox.width / 2 : null;
                if (!this.rotated) {
                    if ((centerLabelY || bbox.y + bbox.height) < bboxgraphic.y) {
                        y1 = centerLabelY || bbox.y + bbox.height;
                        y2 = bboxgraphic.y
                    }
                    else if ((centerLabelY || bbox.y) > bboxgraphic.y + bboxgraphic.height) {
                        y1 = centerLabelY || bbox.y;
                        y2 = bboxgraphic.y + bboxgraphic.height
                    }
                    else
                        return;
                    x1 = Math.round(bbox.x + bbox.width / 2);
                    if (x1 > bboxgraphic.x + bboxgraphic.width)
                        x2 = bboxgraphic.x + bboxgraphic.width;
                    else if (x1 < bboxgraphic.x)
                        x2 = bboxgraphic.x;
                    else
                        x2 = x1
                }
                else {
                    if ((centerLabelX || bbox.x) > bboxgraphic.x + bboxgraphic.width) {
                        x1 = centerLabelX || bbox.x;
                        x2 = bboxgraphic.x + bboxgraphic.width
                    }
                    else if ((centerLabelX || bbox.x + bbox.width) < bboxgraphic.x) {
                        x1 = centerLabelX || bbox.x + bbox.width;
                        x2 = bboxgraphic.x
                    }
                    else
                        return;
                    y1 = Math.round(bbox.y + bbox.height / 2);
                    if (y1 > bboxgraphic.y + bboxgraphic.height)
                        y2 = bboxgraphic.y + bboxgraphic.height;
                    else if (y1 < bboxgraphic.y)
                        y2 = bboxgraphic.y;
                    else
                        y2 = y1
                }
                this.connector.applySettings({points: [x1, y1, x2, y2]})
            },
            getColor: function() {
                return this.options.attributes.fill
            },
            getTooltipFormatObject: function(tooltip) {
                var tooltipFormatObject = this._getFormatObject(tooltip);
                if (this.stackPoints) {
                    if (!tooltip.options.customizeText)
                        tooltip.options.customizeText = function() {
                            return $.map(this.points, function(point, i) {
                                    return point.seriesName + ': ' + point.valueText
                                }).join('\n')
                        };
                    var tooltipStackPointsFormatObject = [];
                    $.each(this.stackPoints, function(i, point) {
                        tooltipStackPointsFormatObject.push(point._getFormatObject(tooltip))
                    });
                    var sharedTooltipFormatObject = {
                            total: tooltipFormatObject.total,
                            argument: tooltipFormatObject.argument,
                            points: tooltipStackPointsFormatObject
                        };
                    this.stackPoints.stackName && (sharedTooltipFormatObject.stackName = this.stackPoints.stackName);
                    return sharedTooltipFormatObject
                }
                else
                    return tooltipFormatObject
            },
            _getFormatObject: function(tooltip) {
                var value = tooltip.formatValueTooltip.call({value: this.initialValue}, tooltip.options);
                return $.extend({}, this.labelFormatObject, {
                        point: this,
                        valueText: value
                    })
            },
            animate: function(complete) {
                var self = this,
                    graphic = self.graphic;
                if (!graphic) {
                    complete && complete();
                    return
                }
                graphic.animate({translate: {
                        x: 0,
                        y: 0
                    }}, undefined, complete)
            },
            hasValue: function() {
                return this.initialValue !== null
            },
            getClassName: function() {
                return this.pointClassName
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file barPoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            statesConsts = series.consts.states,
            isDefined = DX.utils.isDefined,
            CANVAS_POSITION_DEFAULT = 'canvas_position_default';
        var truncateCoord = function(coord, minBounce, maxBounce) {
                if (coord < minBounce)
                    return minBounce;
                if (coord > maxBounce)
                    return maxBounce;
                return coord
            };
        series.BarPoint = series.BasePoint.inherit({
            translate: function(translator) {
                var canvasVisibleArea,
                    minX,
                    minY,
                    y,
                    x;
                this.translator = translator = translator || this.translator;
                if (!this.translator || !this.hasValue())
                    return;
                canvasVisibleArea = translator.getCanvasVisibleArea() || {};
                if (!this.rotated) {
                    x = minX = translator.translateX(this.argument) + (this.xCorrection || 0);
                    y = translator.translateY(this.value);
                    minY = translator.translateY(this.minValue);
                    this.height = Math.abs(y - minY);
                    this._calculateVisibility(Math.min(x, minX), Math.min(y, minY), this.width, this.height);
                    y = truncateCoord(y, canvasVisibleArea.minY, canvasVisibleArea.maxY);
                    minY = truncateCoord(minY, canvasVisibleArea.minY, canvasVisibleArea.maxY);
                    this.x = x;
                    this.minX = minX;
                    this.height = Math.abs(y - minY);
                    this.y = Math.min(y, minY) + (this.yCorrection || 0);
                    this.minY = minY + (this.yCorrection || 0);
                    this.defaultY = translator.translateY(CANVAS_POSITION_DEFAULT);
                    if (this.visible) {
                        if (this.x < canvasVisibleArea.minX) {
                            this.width = this.width - (canvasVisibleArea.minX - this.x);
                            this.x = canvasVisibleArea.minX;
                            this.minX = canvasVisibleArea.minX
                        }
                        if (this.x + this.width > canvasVisibleArea.maxX)
                            this.width = canvasVisibleArea.maxX - this.x
                    }
                }
                else {
                    y = minY = translator.translateY(this.argument) + (this.yCorrection || 0);
                    x = translator.translateX(this.value);
                    minX = translator.translateX(this.minValue);
                    this.width = Math.abs(x - minX);
                    this._calculateVisibility(Math.min(x, minX), Math.min(y, minY), this.width, this.height);
                    x = truncateCoord(x, canvasVisibleArea.minX, canvasVisibleArea.maxX);
                    minX = truncateCoord(minX, canvasVisibleArea.minX, canvasVisibleArea.maxX);
                    this.y = y;
                    this.minY = minY;
                    this.width = Math.abs(x - minX);
                    this.x = Math.min(x, minX) + (this.xCorrection || 0);
                    this.minX = minX + (this.xCorrection || 0);
                    this.defaultX = translator.translateX(CANVAS_POSITION_DEFAULT);
                    if (this.visible) {
                        if (this.y < canvasVisibleArea.minY) {
                            this.height = this.height - (canvasVisibleArea.minY - this.y);
                            this.y = canvasVisibleArea.minY;
                            this.minY = canvasVisibleArea.minY
                        }
                        if (this.y + this.height > canvasVisibleArea.maxY)
                            this.height = canvasVisibleArea.maxY - this.y
                    }
                }
            },
            getTooltipCoords: function() {
                var self = this,
                    x = self.x + self.width / 2,
                    y = self.y + self.height / 2;
                return {
                        x: x,
                        y: y,
                        offset: 0
                    }
            },
            correctCoordinates: function(correctOptions) {
                var correction = correctOptions.offset - Math.round(correctOptions.width / 2);
                if (!this.rotated) {
                    this.width = correctOptions.width;
                    this.xCorrection = correction
                }
                else {
                    this.height = correctOptions.width;
                    this.yCorrection = correction
                }
            },
            drawMarker: function(renderer, group) {
                if (!this.hasValue())
                    return;
                var attributes = this._checkState();
                this.graphic = renderer.createRect(this.x, this.y, this.width, this.height, attributes.r, attributes).append(group)
            },
            _checkState: function() {
                var attributes;
                if (this.isSelected())
                    attributes = this.options.states.selected;
                else if (this.isHovered())
                    attributes = this.options.states.hover;
                else {
                    attributes = this.options.attributes;
                    this.fullState = statesConsts.normalMark
                }
                return attributes
            },
            drawTrackerMarker: function(renderer, trackerGroup) {
                if (!this.hasValue())
                    return;
                var _this = this,
                    y = _this.y,
                    height = _this.height,
                    x = _this.x,
                    width = _this.width;
                if (_this.rotated) {
                    if (width === 1) {
                        width = 9;
                        x -= 4
                    }
                }
                else if (height === 1) {
                    height = 9;
                    y -= 4
                }
                this.trackerGraphic = renderer.createRect(x, y, width, height, _this.options.attributes.r, _this._trackerAttrs).append(trackerGroup);
                this.trackerGraphic.data({point: _this})
            },
            correctConnectorPosition: function() {
                this.callBase(this.getBboxGraphic())
            },
            drawLabel: function(renderer, group) {
                if (!this.hasValue() || !this.options.label.showForZeroValues && !this.labelFormatObject.value)
                    return;
                else
                    this.callBase(renderer, group)
            },
            getBboxGraphic: function() {
                var bboxgraphic = this.graphic && this.graphic.getBBox(),
                    deltaX,
                    deltaY;
                if (bboxgraphic.isEmpty)
                    bboxgraphic = this.getGraphicSettings();
                deltaX = bboxgraphic.x - this.x;
                deltaY = bboxgraphic.y - this.y;
                bboxgraphic.x -= deltaX;
                bboxgraphic.y -= deltaY;
                bboxgraphic.width += 2 * deltaX;
                bboxgraphic.height += 2 * deltaY;
                return bboxgraphic
            },
            correctLabelPosition: function() {
                var bbox = this.insideLabelGroup.getBBox(),
                    bboxgraphic = this.getBboxGraphic(),
                    businessRange = this.translator.getBusinessRange(),
                    isDiscreteValue = this.series.options.valueAxisType === 'discrete',
                    isTop = !isDiscreteValue && (this.initialValue >= 0 && !businessRange.invertY || this.initialValue < 0 && businessRange.invertY) || isDiscreteValue && !businessRange.invertY || this.series.isFullStackedSeries(),
                    isLeft = !isDiscreteValue && (this.initialValue >= 0 && !businessRange.invertX || this.initialValue < 0 && businessRange.invertX) || isDiscreteValue && !businessRange.invertX || this.series.isFullStackedSeries(),
                    x = 0,
                    y = 0;
                if (this.initialValue === 0 && this.series.isFullStackedSeries())
                    if (!this.rotated) {
                        x += bboxgraphic.width / 2;
                        y += this.defaultY - bbox.y - bbox.height - this.LABEL_OFFSET
                    }
                    else {
                        y += bboxgraphic.y - bbox.y - bbox.height / 2 + bboxgraphic.height / 2;
                        x += this.defaultX - bbox.x + this.LABEL_OFFSET
                    }
                else if (this.options.label.position === 'outside')
                    if (!this.rotated) {
                        x += bboxgraphic.width / 2;
                        if (isTop)
                            y += bboxgraphic.y - bbox.y - bbox.height - this.LABEL_OFFSET;
                        else
                            y += bboxgraphic.y + bboxgraphic.height - bbox.y + this.LABEL_OFFSET
                    }
                    else {
                        y += bboxgraphic.y - bbox.y - bbox.height / 2 + bboxgraphic.height / 2;
                        if (isLeft)
                            x += bboxgraphic.x + bboxgraphic.width - bbox.x + this.LABEL_OFFSET;
                        else
                            x += bboxgraphic.x - bbox.x - bbox.width - this.LABEL_OFFSET
                    }
                else if (this.options.label.position === 'inside')
                    if (!this.rotated) {
                        x += bboxgraphic.width / 2;
                        if (isTop)
                            y += bboxgraphic.y - bbox.y - bbox.height + this.LABEL_OFFSET + bbox.height;
                        else
                            y += bboxgraphic.y + bboxgraphic.height - bbox.y - this.LABEL_OFFSET - bbox.height
                    }
                    else {
                        y += bboxgraphic.y - bbox.y - bbox.height / 2 + bboxgraphic.height / 2;
                        if (isLeft)
                            x += bboxgraphic.x + bboxgraphic.width - bbox.x - bbox.width - this.LABEL_OFFSET;
                        else
                            x += bboxgraphic.x - bbox.x + this.LABEL_OFFSET
                    }
                x += this.options.label.horizontalOffset;
                y += this.options.label.verticalOffset;
                this.checkLabelPosition({
                    x: bbox.x + x,
                    y: bbox.y + y,
                    height: bbox.height,
                    width: bbox.width
                }, x, y, bboxgraphic)
            },
            checkLabelPosition: function(bbox, x, y, bboxgraphic) {
                var bboxgraphic = bboxgraphic || this.graphic.getBBox(),
                    visibleArea = this.translator.getCanvasVisibleArea();
                if (bboxgraphic.isEmpty)
                    bboxgraphic = this.getGraphicSettings();
                if (visibleArea.minX <= bboxgraphic.x + bboxgraphic.width && visibleArea.maxX >= bboxgraphic.x && visibleArea.minY <= bboxgraphic.y + bboxgraphic.height && visibleArea.maxY >= bboxgraphic.y) {
                    if (!this.rotated) {
                        if (visibleArea.minX > bbox.x && this.adjustSeriesLabels)
                            x += visibleArea.minX - bbox.x;
                        if (visibleArea.maxX < bbox.x + bbox.width && this.adjustSeriesLabels)
                            x -= bbox.x + bbox.width - visibleArea.maxX;
                        if (visibleArea.minY > bbox.y)
                            y += visibleArea.minY - bbox.y;
                        if (visibleArea.maxY < bbox.y + bbox.height)
                            y -= bbox.y + bbox.height - visibleArea.maxY
                    }
                    if (this.rotated) {
                        if (visibleArea.minX > bbox.x)
                            x += visibleArea.minX - bbox.x;
                        if (visibleArea.maxX < bbox.x + bbox.width)
                            x -= bbox.x + bbox.width - visibleArea.maxX;
                        if (visibleArea.minY > bbox.y && this.adjustSeriesLabels)
                            y += visibleArea.minY - bbox.y;
                        if (visibleArea.maxY < bbox.y + bbox.height && this.adjustSeriesLabels)
                            y -= bbox.y + bbox.height - visibleArea.maxY
                    }
                }
                this.insideLabelGroup.move(~~x, ~~y)
            },
            animate: function() {
                var _this = this,
                    graphic = _this.graphic;
                if (!graphic || !_this.translator)
                    return;
                if (!_this.rotated) {
                    graphic.applySettings({
                        height: 0,
                        y: _this.defaultY,
                        sharpEdges: false
                    });
                    graphic.animate({
                        height: _this.height,
                        y: _this.y
                    })
                }
                else {
                    graphic.applySettings({
                        width: 0,
                        x: _this.defaultX,
                        sharpEdges: false
                    });
                    graphic.animate({
                        width: _this.width,
                        x: _this.x
                    })
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file ohlcPoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            utils = DX.utils,
            statesConsts = series.consts.states,
            formatHelper = DX.formatHelper;
        series.OhlcPoint = series.BasePoint.inherit({
            ctor: function(data) {
                var debug = DX.utils.debug;
                debug.assertParam(data, 'data was not passed');
                debug.assertParam(data.options, 'options were not passed');
                this.LABEL_BACKGROUND_PADDING_X = 8;
                this.LABEL_BACKGROUND_PADDING_Y = 4;
                this.LABEL_OFFSET = 10;
                this.argument = this.initialArgument = data.argument;
                this.openValue = data.openValue;
                this.highValue = data.highValue;
                this.lowValue = data.lowValue;
                this.closeValue = data.closeValue;
                this.value = this.initialValue = data.reductionValue;
                this.originalOpenValue = data.originalOpenValue;
                this.originalCloseValue = data.originalCloseValue;
                this.originalLowValue = data.originalLowValue;
                this.originalHighValue = data.originalHighValue;
                this.originalArgument = data.originalArgument;
                this.tag = data.tag;
                this.options = data.options;
                this.options.attributes && (this.options.attributes.inh = true);
                this.series = data.series;
                this.rotated = !!(this.series && this.series.options && this.series.options.rotated || false);
                this.labelFormatObject = {
                    openValue: this.openValue,
                    highValue: this.highValue,
                    lowValue: this.lowValue,
                    closeValue: this.closeValue,
                    reductionValue: this.initialValue,
                    argument: this.initialArgument,
                    value: this.initialValue,
                    seriesName: this.series.name,
                    originalOpenValue: this.originalOpenValue,
                    originalCloseValue: this.originalCloseValue,
                    originalLowValue: this.originalLowValue,
                    originalHighValue: this.originalHighValue,
                    originalArgument: this.originalArgument
                };
                this.pointClassName = data.pointClassName || ''
            },
            formatLabel: function(options) {
                this.openValueText = formatHelper.format(this.openValue, options.format, options.precision);
                this.highValueText = formatHelper.format(this.highValue, options.format, options.precision);
                this.lowValueText = formatHelper.format(this.lowValue, options.format, options.precision);
                this.closeValueText = formatHelper.format(this.closeValue, options.format, options.precision);
                this.reductionValueText = formatHelper.format(this.reductionValue, options.format, options.precision);
                this.valueText = formatHelper.format(this.value, options.format, options.precision);
                this.argumentText = formatHelper.format(this.argument, options.argumentFormat, options.argumentPrecision);
                return options.customizeText ? options.customizeText.call(this, this) : this.valueText
            },
            translate: function(translator) {
                var _this = this,
                    rotated = _this.rotated,
                    translateArg = rotated ? 'translateY' : 'translateX',
                    translateVal = rotated ? 'translateX' : 'translateY',
                    height,
                    math = Math;
                _this.translator = translator = translator || _this.translator;
                if (!_this.translator || !_this.hasValue())
                    return;
                _this.x = translator[translateArg](_this.argument) + (_this.xCorrection || 0);
                _this.openY = _this.openValue !== null ? translator[translateVal](_this.openValue) : null;
                _this.highY = translator[translateVal](_this.highValue);
                _this.lowY = translator[translateVal](_this.lowValue);
                _this.closeY = _this.closeValue !== null ? translator[translateVal](_this.closeValue) : null;
                height = math.abs(_this.lowY - _this.highY);
                if (!_this.rotated)
                    _this._calculateVisibility(_this.x - _this.width / 2, math.min(_this.lowY, _this.highY), _this.width, height);
                else
                    _this._calculateVisibility(math.min(_this.lowY, _this.highY), _this.x - _this.width / 2, height, _this.width)
            },
            correctCoordinates: function(correctOptions) {
                var minWidth = 1 + 2 * this.options.attributes.lineWidth,
                    maxWidth = 10;
                this.width = correctOptions.width < minWidth ? minWidth : correctOptions.width > maxWidth ? maxWidth : correctOptions.width;
                this.xCorrection = correctOptions.offset
            },
            drawMarker: function(renderer, group) {
                if (!this.hasValue())
                    return;
                var _this = this,
                    attributes,
                    rotated = _this.rotated,
                    pointGroup;
                attributes = _this._checkState();
                switch (_this.pointClassName) {
                    case'dx-candle-reduction':
                        pointGroup = group.reductionMarkersGroup;
                        break;
                    case'dx-candle-default dx-candle-positive':
                        pointGroup = group.defaultPositiveMarkersGroup;
                        break;
                    case'dx-candle-reduction dx-candle-positive':
                        pointGroup = group.reductionPositiveMarkersGroup;
                        break;
                    default:
                        pointGroup = group.defaultMarkersGroup
                }
                _this.drawMarkerInGroup(pointGroup, attributes, renderer)
            },
            _checkState: function() {
                var _this = this,
                    attributes;
                if (_this.isSelected())
                    attributes = _this.options.states.selected;
                else if (_this.isHovered())
                    attributes = _this.options.states.hover;
                else {
                    attributes = _this.options.attributes;
                    _this.fullState = statesConsts.normalMark
                }
                return attributes
            },
            drawMarkerInGroup: function(pointGroup, attributes, renderer) {
                var _this = this,
                    createPoint = this.rotated ? function(x, y) {
                        return {
                                x: y,
                                y: x
                            }
                    } : function(x, y) {
                        return {
                                x: x,
                                y: y
                            }
                    },
                    openValue = _this.openValue,
                    closeValue = _this.closeValue,
                    y;
                if ($.isNumeric(openValue) && $.isNumeric(closeValue)) {
                    if (openValue > closeValue)
                        _this.graphic = renderer.createArea([createPoint(_this.x, _this.highY), createPoint(_this.x, _this.openY), createPoint(_this.x + _this.width / 2, _this.openY), createPoint(_this.x + _this.width / 2, _this.closeY), createPoint(_this.x, _this.closeY), createPoint(_this.x, _this.lowY), createPoint(_this.x, _this.closeY), createPoint(_this.x - _this.width / 2, _this.closeY), createPoint(_this.x - _this.width / 2, _this.openY), createPoint(_this.x, _this.openY)], attributes).append(pointGroup);
                    else if (openValue < closeValue)
                        _this.graphic = renderer.createArea([createPoint(_this.x, _this.highY), createPoint(_this.x, _this.closeY), createPoint(_this.x + _this.width / 2, _this.closeY), createPoint(_this.x + _this.width / 2, _this.openY), createPoint(_this.x, _this.openY), createPoint(_this.x, _this.lowY), createPoint(_this.x, _this.openY), createPoint(_this.x - _this.width / 2, _this.openY), createPoint(_this.x - _this.width / 2, _this.closeY), createPoint(_this.x, _this.closeY)], attributes).append(pointGroup);
                    else if (openValue === closeValue)
                        _this.graphic = renderer.createArea([createPoint(_this.x, _this.highY), createPoint(_this.x, _this.lowY), createPoint(_this.x, _this.closeY), createPoint(_this.x - _this.width / 2, _this.closeY), createPoint(_this.x + _this.width / 2, _this.closeY), createPoint(_this.x, _this.closeY)], attributes).append(pointGroup)
                }
                else if (openValue === closeValue)
                    _this.graphic = renderer.createArea([createPoint(_this.x, _this.highY), createPoint(_this.x, _this.lowY)], attributes).append(pointGroup);
                else {
                    if ($.isNumeric(openValue))
                        y = _this.openY;
                    else
                        y = _this.closeY;
                    _this.graphic = renderer.createArea([createPoint(_this.x, _this.highY), createPoint(_this.x, _this.lowY), createPoint(_this.x, y), createPoint(_this.x - _this.width / 2, y), createPoint(_this.x + _this.width / 2, y), createPoint(_this.x, y)], attributes).append(pointGroup)
                }
            },
            drawTrackerMarker: function(renderer, trackerGroup) {
                if (!this.hasValue())
                    return;
                var _this = this,
                    highY = _this.highY,
                    lowY = _this.lowY,
                    rotated = _this.rotated,
                    math = Math,
                    x,
                    y,
                    width,
                    height;
                if (highY === lowY) {
                    highY = !rotated ? highY - 2 : highY + 2;
                    lowY = !rotated ? lowY + 2 : lowY - 2
                }
                if (!rotated) {
                    x = _this.x - _this.width / 2;
                    y = math.min(lowY, highY);
                    width = _this.width;
                    height = math.abs(lowY - highY)
                }
                else {
                    x = math.min(lowY, highY);
                    y = _this.x - _this.width / 2;
                    width = math.abs(lowY - highY);
                    height = _this.width
                }
                _this.trackerGraphic = renderer.createRect(x, y, width, height, 0, _this._trackerAttrs).append(trackerGroup);
                _this.trackerGraphic.data({point: _this})
            },
            animate: function(){},
            drawLabel: function(renderer, group) {
                if (!this.hasValue())
                    return;
                if (!utils.isDefined(this.labelFormatObject.value))
                    return;
                var labelOptions = this.options.label,
                    labelText = this.formatLabel.call(this.labelFormatObject, labelOptions),
                    rotated = this.rotated;
                if (!utils.isDefined(labelText))
                    return;
                this.labelGroup = renderer.createGroup().append(group);
                this.insideLabelGroup = renderer.createGroup().append(this.labelGroup);
                labelOptions.background['class'] = this.pointClassName;
                if (labelOptions.background.fill && labelOptions.background.fill !== 'none' || labelOptions.background.strokeWidth && labelOptions.background.stroke && labelOptions.background.stroke !== 'none') {
                    labelOptions.background.fill = this.options.attributes.stroke;
                    this.labelBackground = rotated ? renderer.createRect(this.highY, this.x, 0, 0, 0, labelOptions.background).append(this.insideLabelGroup) : renderer.createRect(this.x, this.highY, 0, 0, 0, labelOptions.background).append(this.insideLabelGroup)
                }
                this.label = rotated ? renderer.createText(labelText, this.highY, this.x, labelOptions.attributes).append(this.insideLabelGroup) : renderer.createText(labelText, this.x, this.highY, labelOptions.attributes).append(this.insideLabelGroup);
                this.correctBackgroundPosition();
                this.rotateLabel();
                this.correctLabelPosition()
            },
            correctLabelPosition: function() {
                var bbox = this.insideLabelGroup.getBBox(),
                    bboxgraphic = this.graphic.getBBox(),
                    rotated = this.rotated,
                    x = 0,
                    y = 0;
                if (!rotated)
                    y += bboxgraphic.y - bbox.y - bbox.height - this.LABEL_OFFSET;
                else
                    x += bboxgraphic.x - bbox.x + bboxgraphic.width + this.LABEL_OFFSET;
                x += this.options.label.horizontalOffset;
                y += this.options.label.verticalOffset;
                this.checkLabelPosition({
                    x: bbox.x + x,
                    y: bbox.y + y,
                    height: bbox.height,
                    width: bbox.width
                }, x, y)
            },
            checkLabelPosition: function(bbox, x, y) {
                var visibleArea = this.translator.getCanvasVisibleArea(),
                    bboxgraphic = this.graphic.getBBox();
                if (visibleArea.minX <= bboxgraphic.x + bboxgraphic.width && visibleArea.maxX >= bboxgraphic.x) {
                    if (visibleArea.minX > bbox.x && this.adjustSeriesLabels)
                        x += visibleArea.minX - bbox.x;
                    if (visibleArea.maxX < bbox.x + bbox.width && this.adjustSeriesLabels)
                        x -= bbox.x + bbox.width - visibleArea.maxX;
                    if (visibleArea.minY > bbox.y)
                        y += visibleArea.minY - bbox.y;
                    if (visibleArea.maxY < bbox.y + bbox.height)
                        y -= bbox.y + bbox.height - visibleArea.maxY
                }
                this.insideLabelGroup.move(~~x, ~~y)
            },
            getTooltipCoords: function() {
                var x,
                    y,
                    min,
                    max,
                    math = Math,
                    minValue = math.min(this.lowY, this.highY),
                    maxValue = math.max(this.lowY, this.highY),
                    visibleArea = this.translator.getCanvasVisibleArea();
                if (this.graphic) {
                    if (!this.rotated) {
                        min = math.max(visibleArea.minY, minValue);
                        max = math.min(visibleArea.maxY, maxValue);
                        x = this.x;
                        y = min + (max - min) / 2
                    }
                    else {
                        min = math.max(visibleArea.minX, minValue);
                        max = math.min(visibleArea.maxX, maxValue);
                        y = this.x;
                        x = min + (max - min) / 2
                    }
                    return {
                            x: x,
                            y: y,
                            offset: 0
                        }
                }
            },
            getTooltipFormatObject: function(tooltip) {
                var highValue = tooltip.formatValueTooltip.call({value: this.highValue}, tooltip.options),
                    openValue = tooltip.formatValueTooltip.call({value: this.openValue}, tooltip.options),
                    closeValue = tooltip.formatValueTooltip.call({value: this.closeValue}, tooltip.options),
                    lowValue = tooltip.formatValueTooltip.call({value: this.lowValue}, tooltip.options);
                return $.extend({}, this.labelFormatObject, {
                        valueText: 'h: ' + highValue + (openValue !== '' ? ' o: ' + openValue : '') + (closeValue !== '' ? ' c: ' + closeValue : '') + ' l: ' + lowValue,
                        highValueText: highValue,
                        openValueText: openValue,
                        closeValueText: closeValue,
                        lowValueText: lowValue,
                        point: this
                    })
            },
            getColor: function() {
                return this.options.attributes.stroke
            },
            hasValue: function() {
                return this.highValue !== null && this.lowValue !== null
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file stockPoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            statesConsts = series.consts.states,
            OhlcPoint = series.OhlcPoint;
        series.StockPoint = series.OhlcPoint.inherit({
            correctCoordinates: function(correctOptions) {
                var minWidth = 2 + this.options.attributes.lineWidth,
                    maxWidth = 10;
                this.width = correctOptions.width < minWidth ? minWidth : correctOptions.width > maxWidth ? maxWidth : correctOptions.width;
                this.xCorrection = correctOptions.offset
            },
            drawMarkerInGroup: function(pointGroup, attributes, renderer) {
                var createPoint = this.rotated ? function(x, y) {
                        return {
                                x: y,
                                y: x
                            }
                    } : function(x, y) {
                        return {
                                x: x,
                                y: y
                            }
                    },
                    openYExist = $.isNumeric(this.openY),
                    closeYExist = $.isNumeric(this.closeY);
                this.graphic = renderer.createPath([createPoint(this.x, this.highY), openYExist && createPoint(this.x, this.openY), openYExist && createPoint(this.x - this.width / 2, this.openY), openYExist && createPoint(this.x, this.openY), closeYExist && createPoint(this.x, this.closeY), closeYExist && createPoint(this.x + this.width / 2, this.closeY), closeYExist && createPoint(this.x, this.closeY), createPoint(this.x, this.lowY)], attributes).append(pointGroup)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangePoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            utils = DX.utils,
            eventsConsts = series.consts.events,
            statesConsts = series.consts.states;
        series.RangePoint = series.BasePoint.inherit({
            ctor: function(data) {
                this.callBase(data);
                this.minValue = this.initialMinValue = data.minValue !== undefined ? data.minValue : 'default';
                this.originalMinValue = data.originalMinValue;
                this.minLabelFormatObject = {
                    argument: this.initialArgument,
                    value: this.initialMinValue,
                    seriesName: this.series.name,
                    originalMinValue: this.originalMinValue,
                    originalArgument: this.originalArgument
                }
            },
            dispose: function() {
                var _this = this;
                _this.minLabel = null;
                _this.minLabelBackground = null;
                _this.minConnector = null;
                _this.insideMinLabelGroup = null;
                _this.minLabelGroup = null;
                _this.maxLabel = null;
                _this.maxLabelBackground = null;
                _this.maxConnector = null;
                _this.insideMaxLabelGroup = null;
                _this.maxLabelGroup = null;
                _this.topPoints = null;
                _this.bottomPoints = null;
                _this.minLabelFormatObject = null;
                _this.callBase()
            },
            getTooltipCoords: function() {
                var x,
                    y,
                    min,
                    max,
                    minValue,
                    visibleArea = this.translator.getCanvasVisibleArea();
                if (!this.rotated) {
                    minValue = Math.min(this.y, this.minY);
                    x = this.x;
                    min = visibleArea.minY > minValue ? visibleArea.minY : minValue;
                    max = visibleArea.maxY < minValue + this.height ? visibleArea.maxY : minValue + this.height;
                    y = min + (max - min) / 2
                }
                else {
                    minValue = Math.min(this.x, this.minX);
                    y = this.y;
                    min = visibleArea.minX > minValue ? visibleArea.minX : minValue;
                    max = visibleArea.maxX < minValue + this.width ? visibleArea.maxX : minValue + this.width;
                    x = min + (max - min) / 2
                }
                return {
                        x: x,
                        y: y,
                        offset: 0
                    }
            },
            translate: function(translator) {
                this.minX = this.minY = translator.translateY(this.minValue);
                this.callBase(translator);
                if (!this.rotated) {
                    this.height = Math.abs(this.minY - this.y);
                    this.width = 0
                }
                else {
                    this.width = Math.abs(this.x - this.minX);
                    this.height = 0
                }
            },
            isInVisibleArea: function() {
                var minArgument = Math.min(this.minX, this.x) || this.x,
                    maxArgument = Math.max(this.minX, this.x) || this.x,
                    maxValue = Math.max(this.minY, this.y) || this.y,
                    minValue = Math.min(this.minY, this.y) || this.y,
                    notVisibleBothMarkersRight,
                    notVisibleBothMarkersLeft,
                    notVisibleBothMarkersBottom,
                    notVisibleBothMarkersTop,
                    visibleTopMarker = true,
                    visibleBottomMarker = true,
                    visibleRangeArea = true,
                    visibleArea;
                if (this.translator && this.translator.getCanvasVisibleArea) {
                    visibleArea = this.translator.getCanvasVisibleArea();
                    notVisibleBothMarkersRight = visibleArea.maxX < minArgument && visibleArea.maxX < maxArgument;
                    notVisibleBothMarkersLeft = visibleArea.minX > minArgument && visibleArea.minX > maxArgument;
                    notVisibleBothMarkersTop = visibleArea.minY > minValue && visibleArea.minY > maxValue;
                    notVisibleBothMarkersBottom = visibleArea.maxY < minValue && visibleArea.maxY < maxValue;
                    if (notVisibleBothMarkersTop || notVisibleBothMarkersBottom || notVisibleBothMarkersRight || notVisibleBothMarkersLeft)
                        visibleTopMarker = visibleBottomMarker = visibleRangeArea = false;
                    else if (!this.rotated) {
                        visibleTopMarker = visibleArea.minY < minValue && visibleArea.maxY > minValue;
                        visibleBottomMarker = visibleArea.minY < maxValue && visibleArea.maxY > maxValue
                    }
                    else {
                        visibleBottomMarker = visibleArea.minX < minArgument && visibleArea.maxX > minArgument;
                        visibleTopMarker = visibleArea.minX < maxArgument && visibleArea.maxX > maxArgument
                    }
                }
                this.visibleTopMarker = visibleTopMarker;
                this.visibleBottomMarker = visibleBottomMarker;
                this.visibleRangeArea = visibleRangeArea;
                return visibleRangeArea
            },
            drawMarker: function(renderer, group) {
                if (!this.hasValue())
                    return;
                var radius = this.options.attributes.r,
                    topMarker,
                    x,
                    y,
                    bottomMarker,
                    markerGroup = renderer.createGroup().append(group);
                switch (this.options.symbol) {
                    case'circle':
                        if (!this.rotated) {
                            x = this.x;
                            y = Math.min(this.y, this.minY)
                        }
                        else {
                            x = Math.min(this.x, this.minX);
                            y = this.y
                        }
                        topMarker = this.visibleTopMarker ? renderer.createCircle(x + this.width, y, radius, this.options.attributes).append(markerGroup) : null;
                        bottomMarker = this.visibleBottomMarker ? renderer.createCircle(x, y + this.height, radius, this.options.attributes).append(markerGroup) : null;
                        break;
                    case'square':
                    case'polygon':
                    case'triangle':
                    case'cross':
                        topMarker = this.visibleTopMarker ? renderer.createArea(this.topPoints, this.options.attributes).append(markerGroup) : null;
                        bottomMarker = this.visibleBottomMarker ? renderer.createArea(this.bottomPoints, this.options.attributes).append(markerGroup) : null;
                        break
                }
                this.graphic = markerGroup;
                this.graphic.topMarker = topMarker;
                this.graphic.bottomMarker = bottomMarker;
                this._checkState()
            },
            _populatePointShape: function(target, radius) {
                var self = this,
                    floorHalfRadius,
                    ceilHalfRadius,
                    topX,
                    topY,
                    bottomX,
                    bottomY;
                if (!this.rotated) {
                    topX = bottomX = self.x;
                    topY = Math.min(self.y, self.minY);
                    bottomY = Math.max(self.y, self.minY)
                }
                else {
                    topX = Math.max(self.x, self.minX);
                    bottomX = Math.min(self.x, self.minX);
                    topY = bottomY = self.y
                }
                if (self.options.symbol === 'square') {
                    target.topPoints = [{
                            x: topX - radius,
                            y: topY - radius
                        }, {
                            x: topX + radius,
                            y: topY - radius
                        }, {
                            x: topX + radius,
                            y: topY + radius
                        }, {
                            x: topX - radius,
                            y: topY + radius
                        }, {
                            x: topX - radius,
                            y: topY - radius
                        }];
                    target.bottomPoints = [{
                            x: bottomX - radius,
                            y: bottomY - radius
                        }, {
                            x: bottomX + radius,
                            y: bottomY - radius
                        }, {
                            x: bottomX + radius,
                            y: bottomY + radius
                        }, {
                            x: bottomX - radius,
                            y: bottomY + radius
                        }, {
                            x: bottomX - radius,
                            y: bottomY - radius
                        }]
                }
                if (self.options.symbol === 'polygon') {
                    target.topPoints = [{
                            x: topX - radius,
                            y: topY
                        }, {
                            x: topX,
                            y: topY - radius
                        }, {
                            x: topX + radius,
                            y: topY
                        }, {
                            x: topX,
                            y: topY + radius
                        }, {
                            x: topX - radius,
                            y: topY
                        }];
                    target.bottomPoints = [{
                            x: bottomX - radius,
                            y: bottomY
                        }, {
                            x: bottomX,
                            y: bottomY - radius
                        }, {
                            x: bottomX + radius,
                            y: bottomY
                        }, {
                            x: bottomX,
                            y: bottomY + radius
                        }, {
                            x: bottomX - radius,
                            y: bottomY
                        }]
                }
                if (self.options.symbol === 'triangle') {
                    target.topPoints = [{
                            x: topX - radius,
                            y: topY - radius
                        }, {
                            x: topX + radius,
                            y: topY - radius
                        }, {
                            x: topX,
                            y: topY + radius
                        }, {
                            x: topX - radius,
                            y: topY - radius
                        }];
                    target.bottomPoints = [{
                            x: bottomX - radius,
                            y: bottomY - radius
                        }, {
                            x: bottomX + radius,
                            y: bottomY - radius
                        }, {
                            x: bottomX,
                            y: bottomY + radius
                        }, {
                            x: bottomX - radius,
                            y: bottomY - radius
                        }]
                }
                if (self.options.symbol === 'cross') {
                    floorHalfRadius = Math.floor(radius / 2);
                    ceilHalfRadius = Math.ceil(radius / 2);
                    target.topPoints = [{
                            x: topX - radius,
                            y: topY - floorHalfRadius
                        }, {
                            x: topX - floorHalfRadius,
                            y: topY - radius
                        }, {
                            x: topX,
                            y: topY - ceilHalfRadius
                        }, {
                            x: topX + floorHalfRadius,
                            y: topY - radius
                        }, {
                            x: topX + radius,
                            y: topY - floorHalfRadius
                        }, {
                            x: topX + ceilHalfRadius,
                            y: topY
                        }, {
                            x: topX + radius,
                            y: topY + floorHalfRadius
                        }, {
                            x: topX + floorHalfRadius,
                            y: topY + radius
                        }, {
                            x: topX,
                            y: topY + ceilHalfRadius
                        }, {
                            x: topX - floorHalfRadius,
                            y: topY + radius
                        }, {
                            x: topX - radius,
                            y: topY + floorHalfRadius
                        }, {
                            x: topX - ceilHalfRadius,
                            y: topY
                        }];
                    target.bottomPoints = [{
                            x: bottomX - radius,
                            y: bottomY - floorHalfRadius
                        }, {
                            x: bottomX - floorHalfRadius,
                            y: bottomY - radius
                        }, {
                            x: bottomX,
                            y: bottomY - ceilHalfRadius
                        }, {
                            x: bottomX + floorHalfRadius,
                            y: bottomY - radius
                        }, {
                            x: bottomX + radius,
                            y: bottomY - floorHalfRadius
                        }, {
                            x: bottomX + ceilHalfRadius,
                            y: bottomY
                        }, {
                            x: bottomX + radius,
                            y: bottomY + floorHalfRadius
                        }, {
                            x: bottomX + floorHalfRadius,
                            y: bottomY + radius
                        }, {
                            x: bottomX,
                            y: bottomY + ceilHalfRadius
                        }, {
                            x: bottomX - floorHalfRadius,
                            y: bottomY + radius
                        }, {
                            x: bottomX - radius,
                            y: bottomY + floorHalfRadius
                        }, {
                            x: bottomX - ceilHalfRadius,
                            y: bottomY
                        }]
                }
            },
            drawTrackerMarker: function(renderer, trackerGroup) {
                if (!this.hasValue())
                    return;
                var _this = this,
                    options = _this.options,
                    radius = options.trackerR || _this.storeTrackerR(),
                    x,
                    y;
                if (!_this.rotated) {
                    x = _this.x - radius;
                    y = Math.min(_this.y, _this.minY) - radius
                }
                else {
                    x = Math.min(_this.x, _this.minX) - radius;
                    y = _this.y - radius
                }
                _this.trackerGraphic = renderer.createRect(x, y, _this.width + 2 * radius, _this.height + 2 * radius, 0, _this._trackerAttrs).append(trackerGroup);
                _this.trackerGraphic.data({point: _this})
            },
            applyStyle: function(style) {
                if (this.graphic) {
                    this._populatePointShape(style, style.r);
                    if (this.graphic.topMarker)
                        this.graphic.topMarker.applySettings(style.topPoints ? {
                            points: style.topPoints,
                            style: style
                        } : style);
                    if (this.graphic.bottomMarker)
                        this.graphic.bottomMarker.applySettings(style.bottomPoints ? {
                            points: style.bottomPoints,
                            style: style
                        } : style)
                }
            },
            applyNormalStyle: function() {
                this.applyStyle(this.options.states.normal);
                return this.callBase()
            },
            applyHoverStyle: function() {
                this.applyStyle(this.options.states.hover);
                return this.callBase()
            },
            applySelectionStyle: function() {
                this.applyStyle(this.options.states.selected);
                return this.callBase()
            },
            drawLabel: function(renderer, group) {
                if (!this.hasValue())
                    return;
                if (!utils.isDefined(this.labelFormatObject.value) || !utils.isDefined(this.minLabelFormatObject.value))
                    return;
                var labelOptions = this.options.label,
                    maxLabelText = this.formatLabel.call(this.labelFormatObject, labelOptions),
                    minLabelText = this.formatLabel.call(this.minLabelFormatObject, labelOptions),
                    businessRange = this.translator.getBusinessRange(),
                    isDiscreteValue = this.series.options.valueAxisType === 'discrete',
                    notInverted = isDiscreteValue && (!businessRange.invertY && !this.rotated || businessRange.invertX && this.rotated) || !isDiscreteValue && this.value > this.minValue && (!businessRange.invertY && !this.rotated || !businessRange.invertX && this.rotated);
                if (!utils.isDefined(maxLabelText) || !utils.isDefined(minLabelText))
                    return;
                this.labelGroup = renderer.createGroup().append(group);
                if (this.options.label.connector && this.options.label.connector.strokeWidth) {
                    if (this.visibleTopMarker)
                        this.maxConnector = renderer.createLine(0, 0, 0, 0, this.options.label.connector).append(this.labelGroup);
                    if (this.visibleBottomMarker)
                        this.minConnector = renderer.createLine(0, 0, 0, 0, this.options.label.connector).append(this.labelGroup)
                }
                this.maxLabelGroup = renderer.createGroup().append(this.labelGroup);
                this.insideMaxLabelGroup = renderer.createGroup().append(this.maxLabelGroup);
                this.minLabelGroup = renderer.createGroup().append(this.labelGroup);
                this.insideMinLabelGroup = renderer.createGroup().append(this.minLabelGroup);
                if (labelOptions.background.fill && labelOptions.background.fill !== 'none' || labelOptions.background.strokeWidth && labelOptions.background.stroke && labelOptions.background.stroke !== 'none') {
                    this.maxLabelBackground = renderer.createRect(this.x, this.y, 0, 0, 0, labelOptions.background).append(this.insideMaxLabelGroup);
                    this.minLabelBackground = renderer.createRect(this.x, this.y, 0, 0, 0, labelOptions.background).append(this.insideMinLabelGroup)
                }
                this.maxLabel = renderer.createText(notInverted ? maxLabelText : minLabelText, this.x, this.y, labelOptions.attributes).append(this.insideMaxLabelGroup);
                this.minLabel = renderer.createText(notInverted ? minLabelText : maxLabelText, this.x, this.y, labelOptions.attributes).append(this.insideMinLabelGroup);
                this.correctLabel();
                this.correctConnectorPosition(this.maxLabelGroup.getBBox(), this.maxConnector);
                this.correctConnectorPosition(this.minLabelGroup.getBBox(), this.minConnector)
            },
            rotateLabel: function() {
                var bboxmax = this.insideMaxLabelGroup.getBBox(),
                    bboxmin = this.insideMinLabelGroup.getBBox(),
                    labelOptions = this.options.label;
                this.insideMaxLabelGroup.applySettings({
                    x: bboxmax.x + bboxmax.width / 2,
                    y: bboxmax.y + bboxmax.height / 2,
                    rotate: labelOptions.rotationAngle
                });
                this.insideMinLabelGroup.applySettings({
                    x: bboxmin.x + bboxmin.width / 2,
                    y: bboxmin.y + bboxmin.height / 2,
                    rotate: labelOptions.rotationAngle
                })
            },
            correctLabelPosition: function() {
                var maxbbox = this.insideMaxLabelGroup.getBBox(),
                    minbbox = this.insideMinLabelGroup.getBBox(),
                    topBBoxgraphic = this.graphic && this.graphic.topMarker ? this.graphic.topMarker.getBBox() : {
                        x: this.rotated ? Math.max(this.x, this.minX) : this.x,
                        y: !this.rotated ? Math.min(this.y, this.minY) : this.y,
                        height: 0,
                        width: 0
                    },
                    bottomBBoxgraphic = this.graphic && this.graphic.bottomMarker ? this.graphic.bottomMarker.getBBox() : {
                        x: this.rotated ? Math.min(this.x, this.minX) : this.x,
                        y: !this.rotated ? Math.max(this.y, this.minY) : this.y,
                        height: 0,
                        width: 0
                    },
                    x1 = 0,
                    y1 = 0,
                    x2 = 0,
                    y2 = 0;
                if (this.options.label.position === 'outside')
                    if (!this.rotated) {
                        y1 += topBBoxgraphic.y - maxbbox.y - maxbbox.height - this.LABEL_OFFSET;
                        y2 += bottomBBoxgraphic.y + bottomBBoxgraphic.height - minbbox.y + this.LABEL_OFFSET
                    }
                    else {
                        y1 = y2 += topBBoxgraphic.y - maxbbox.y - maxbbox.height / 2 + topBBoxgraphic.height / 2;
                        x1 += topBBoxgraphic.x + topBBoxgraphic.width - maxbbox.x + this.LABEL_OFFSET;
                        x2 += bottomBBoxgraphic.x - minbbox.x - minbbox.width - this.LABEL_OFFSET
                    }
                else if (this.options.label.position === 'inside')
                    if (!this.rotated) {
                        y1 += topBBoxgraphic.y + topBBoxgraphic.height - maxbbox.y + this.LABEL_OFFSET;
                        y2 += bottomBBoxgraphic.y - minbbox.y - minbbox.height - this.LABEL_OFFSET
                    }
                    else {
                        y1 = y2 += topBBoxgraphic.y - maxbbox.y - maxbbox.height / 2 + topBBoxgraphic.height / 2;
                        x1 += topBBoxgraphic.x - maxbbox.x - maxbbox.width - this.LABEL_OFFSET;
                        x2 += bottomBBoxgraphic.x + bottomBBoxgraphic.width - minbbox.x + this.LABEL_OFFSET
                    }
                x1 += this.options.label.horizontalOffset;
                y1 += this.options.label.verticalOffset;
                x2 += this.options.label.horizontalOffset;
                y2 += this.options.label.verticalOffset;
                this.checkLabelPosition(x1, y1, x2, y2)
            },
            checkLabelPosition: function(x1, y1, x2, y2) {
                var maxgroupbbox = this.insideMaxLabelGroup.getBBox(),
                    mingroupbbox = this.insideMinLabelGroup.getBBox(),
                    newMaxbbox = {},
                    newMinbbox = {},
                    topBBoxgraphic = this.graphic && this.graphic.topMarker ? this.graphic.topMarker.getBBox() : {
                        x: this.rotated ? Math.max(this.x, this.minX) : this.x,
                        y: !this.rotated ? Math.min(this.y, this.minY) : this.y,
                        height: 0,
                        width: 0
                    },
                    bottomBBoxgraphic = this.graphic && this.graphic.bottomMarker ? this.graphic.bottomMarker.getBBox() : {
                        x: this.rotated ? Math.min(this.x, this.minX) : this.x,
                        y: !this.rotated ? Math.max(this.y, this.minY) : this.y,
                        height: 0,
                        width: 0
                    },
                    maxX = maxgroupbbox.x + x1,
                    maxY = maxgroupbbox.y + y1,
                    minX = mingroupbbox.x + x2,
                    minY = mingroupbbox.y + y2;
                var visibleArea = this.translator.getCanvasVisibleArea();
                if (this.visibleRangeArea) {
                    if (!this.rotated) {
                        if (visibleArea.minX > maxX && this.adjustSeriesLabels)
                            x1 += visibleArea.minX - maxX;
                        if (visibleArea.minX > minX && this.adjustSeriesLabels)
                            x2 += visibleArea.minX - minX;
                        if (visibleArea.maxX < maxX + maxgroupbbox.width && this.adjustSeriesLabels)
                            x1 -= maxX + maxgroupbbox.width - visibleArea.maxX;
                        if (visibleArea.maxX < minX + mingroupbbox.width && this.adjustSeriesLabels)
                            x2 -= minX + mingroupbbox.width - visibleArea.maxX;
                        if (visibleArea.minY > maxY)
                            y1 += visibleArea.minY - maxY;
                        if (visibleArea.maxY < minY + mingroupbbox.height)
                            y2 -= minY + mingroupbbox.height - visibleArea.maxY;
                        newMaxbbox.y = maxgroupbbox.y + y1;
                        newMinbbox.y = mingroupbbox.y + y2;
                        if (newMaxbbox.y + maxgroupbbox.height > newMinbbox.y) {
                            y1 -= (newMaxbbox.y + maxgroupbbox.height - newMinbbox.y) / 2;
                            y2 += (newMaxbbox.y + maxgroupbbox.height - newMinbbox.y) / 2;
                            newMaxbbox.y = maxgroupbbox.y + y1;
                            newMinbbox.y = mingroupbbox.y + y2;
                            if (visibleArea.minY > newMaxbbox.y) {
                                y2 += visibleArea.minY - newMaxbbox.y;
                                y1 += visibleArea.minY - newMaxbbox.y
                            }
                            else if (visibleArea.maxY < newMinbbox.y + mingroupbbox.height) {
                                y1 -= newMinbbox.y + mingroupbbox.height - visibleArea.maxY;
                                y2 -= newMinbbox.y + mingroupbbox.height - visibleArea.maxY
                            }
                        }
                    }
                    if (this.rotated) {
                        if (visibleArea.minX > minX)
                            x2 += visibleArea.minX - minX;
                        if (visibleArea.maxX < maxX + maxgroupbbox.width)
                            x1 -= maxX + maxgroupbbox.width - visibleArea.maxX;
                        if (visibleArea.minY > minY && this.adjustSeriesLabels)
                            y2 += visibleArea.minY - minY;
                        if (visibleArea.minY > maxY && this.adjustSeriesLabels)
                            y1 += visibleArea.minY - maxY;
                        if (visibleArea.maxY < minY + mingroupbbox.height && this.adjustSeriesLabels)
                            y2 -= minY + mingroupbbox.height - visibleArea.maxY;
                        if (visibleArea.maxY < maxY + maxgroupbbox.height && this.adjustSeriesLabels)
                            y1 -= maxY + maxgroupbbox.height - visibleArea.maxY;
                        newMaxbbox.x = maxgroupbbox.x + x1;
                        newMinbbox.x = mingroupbbox.x + x2;
                        if (newMaxbbox.x < newMinbbox.x + mingroupbbox.width) {
                            x1 += (newMinbbox.x + mingroupbbox.width - newMaxbbox.x) / 2;
                            x2 -= (newMinbbox.x + mingroupbbox.width - newMaxbbox.x) / 2;
                            newMaxbbox.x = maxgroupbbox.x + x1;
                            newMinbbox.x = mingroupbbox.x + x2;
                            if (visibleArea.minX > newMinbbox.x) {
                                x2 += visibleArea.minX - newMinbbox.x;
                                x1 += visibleArea.minX - newMinbbox.x
                            }
                            else if (visibleArea.maxX < newMaxbbox.x + maxgroupbbox.width) {
                                x1 -= newMaxbbox.x + maxgroupbbox.width - visibleArea.maxX;
                                x2 -= newMaxbbox.x + maxgroupbbox.width - visibleArea.maxX
                            }
                        }
                    }
                }
                this.insideMaxLabelGroup.move(~~x1, ~~y1);
                this.insideMinLabelGroup.move(~~x2, ~~y2)
            },
            correctBackgroundPosition: function() {
                if (!this.maxLabelBackground || !this.minLabelBackground)
                    return;
                var maxbbox = this.maxLabel.getBBox(),
                    minbbox = this.minLabel.getBBox(),
                    x1 = maxbbox.x - this.LABEL_BACKGROUND_PADDING_X,
                    x2 = minbbox.x - this.LABEL_BACKGROUND_PADDING_X,
                    y1 = maxbbox.y - this.LABEL_BACKGROUND_PADDING_Y,
                    y2 = minbbox.y - this.LABEL_BACKGROUND_PADDING_Y,
                    width1 = maxbbox.width + 2 * this.LABEL_BACKGROUND_PADDING_X,
                    width2 = minbbox.width + 2 * this.LABEL_BACKGROUND_PADDING_X,
                    height1 = maxbbox.height + 2 * this.LABEL_BACKGROUND_PADDING_Y,
                    height2 = minbbox.height + 2 * this.LABEL_BACKGROUND_PADDING_Y;
                this.maxLabelBackground.applySettings({
                    x: x1,
                    y: y1,
                    width: width1,
                    height: height1
                });
                this.minLabelBackground.applySettings({
                    x: x2,
                    y: y2,
                    width: width2,
                    height: height2
                })
            },
            correctConnectorPosition: function(bbox, connector) {
                if (!connector)
                    return;
                var bboxgraphic = this.graphic ? this.graphic.getBBox() : {
                        x: this.rotated ? Math.min(this.x, this.minX) : this.x,
                        y: !this.rotated ? Math.min(this.y, this.minY) : this.y,
                        height: this.height,
                        width: this.width
                    },
                    centerLabelY = this.maxLabelBackground || this.minLabelBackground ? bbox.y + bbox.height / 2 : null,
                    centerLabelX = this.maxLabelBackground || this.minLabelBackground ? bbox.x + bbox.width / 2 : null,
                    x1,
                    x2,
                    y1,
                    y2;
                if (!this.rotated) {
                    if ((centerLabelY || bbox.y + bbox.height) < bboxgraphic.y) {
                        y1 = centerLabelY || bbox.y + bbox.height;
                        y2 = bboxgraphic.y
                    }
                    else if ((centerLabelY || bbox.y) > bboxgraphic.y + bboxgraphic.height) {
                        y1 = centerLabelY || bbox.y;
                        y2 = bboxgraphic.y + bboxgraphic.height
                    }
                    else
                        return false;
                    x1 = Math.round(bbox.x + bbox.width / 2);
                    if (x1 > bboxgraphic.x + bboxgraphic.width)
                        x2 = bboxgraphic.x + bboxgraphic.width;
                    else if (x1 < bboxgraphic.x)
                        x2 = bboxgraphic.x;
                    else
                        x2 = x1
                }
                else {
                    if ((centerLabelX || bbox.x) > bboxgraphic.x + bboxgraphic.width) {
                        x1 = centerLabelX || bbox.x;
                        x2 = bboxgraphic.x + bboxgraphic.width
                    }
                    else if ((centerLabelX || bbox.x + bbox.width) < bboxgraphic.x) {
                        x1 = centerLabelX || bbox.x + bbox.width;
                        x2 = bboxgraphic.x
                    }
                    else
                        return false;
                    y1 = Math.round(bbox.y + bbox.height / 2);
                    if (y1 > bboxgraphic.y + bboxgraphic.height)
                        y2 = bboxgraphic.y + bboxgraphic.height;
                    else if (y1 < bboxgraphic.y)
                        y2 = bboxgraphic.y;
                    else
                        y2 = y1
                }
                connector.applySettings({points: [x1, y1, x2, y2]})
            },
            getTooltipFormatObject: function(tooltip) {
                var minValue = tooltip.formatValueTooltip.call({value: this.initialMinValue}, tooltip.options),
                    value = tooltip.formatValueTooltip.call({value: this.initialValue}, tooltip.options);
                return {
                        argument: this.initialArgument,
                        valueText: minValue + ' - ' + value,
                        rangeValue1Text: minValue,
                        rangeValue2Text: value,
                        rangeValue1: this.initialMinValue,
                        rangeValue2: this.initialValue,
                        seriesName: this.series.name,
                        point: this,
                        originalMinValue: this.originalMinValue,
                        originalValue: this.originalValue,
                        originalArgument: this.originalArgument
                    }
            },
            animate: function() {
                var _this = this,
                    graphic = _this.graphic;
                if (!graphic || !_this.translator)
                    return;
                if (!_this.rotated) {
                    if (graphic.topMarker)
                        graphic.topMarker.move(0, _this.defaultY - Math.min(_this.minY, _this.y));
                    if (graphic.bottomMarker)
                        graphic.bottomMarker.move(0, _this.defaultY - Math.max(_this.minY, _this.y))
                }
                else {
                    if (graphic.topMarker)
                        graphic.topMarker.move(_this.defaultX - Math.max(_this.minX, _this.x), 0);
                    if (graphic.bottomMarker)
                        graphic.bottomMarker.move(_this.defaultX - Math.min(_this.minX, _this.x), 0)
                }
                if (graphic.topMarker)
                    graphic.topMarker.move(0, 0, true);
                if (graphic.bottomMarker)
                    graphic.bottomMarker.move(0, 0, true)
            },
            hasValue: function() {
                return this.initialValue !== null && this.initialMinValue !== null
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangeBarPoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            BarPoint = series.BarPoint,
            utils = DX.utils;
        series.RangeBarPoint = series.BarPoint.inherit({
            ctor: function(data) {
                this.callBase(data);
                this.minValue = this.initialMinValue = data.minValue !== undefined ? data.minValue : 'default';
                this.originalMinValue = data.originalMinValue;
                this.minLabelFormatObject = {
                    argument: this.initialArgument,
                    value: this.initialMinValue,
                    seriesName: this.options.seriesName,
                    originalMinValue: this.originalMinValue,
                    originalArgument: this.originalArgument
                }
            },
            dispose: function() {
                var _this = this;
                _this.minLabel = null;
                _this.minLabelBackground = null;
                _this.minConnector = null;
                _this.insideMinLabelGroup = null;
                _this.minLabelGroup = null;
                _this.maxLabel = null;
                _this.maxLabelBackground = null;
                _this.maxConnector = null;
                _this.insideMaxLabelGroup = null;
                _this.maxLabelGroup = null;
                _this.minLabelFormatObject = null;
                _this.callBase()
            },
            translate: function(translator) {
                if (!this.hasValue())
                    return;
                this.callBase(translator);
                if (this.rotated)
                    this.width = this.width || 1;
                else
                    this.height = this.height || 1
            },
            drawLabel: function(renderer, group) {
                if (!this.hasValue() && (!utils.isDefined(this.labelFormatObject.value) || !utils.isDefined(this.minLabelFormatObject.value)))
                    return;
                var labelOptions = this.options.label,
                    maxLabelText = this.formatLabel.call(this.labelFormatObject, labelOptions),
                    minLabelText = this.formatLabel.call(this.minLabelFormatObject, labelOptions),
                    businessRange = this.translator.getBusinessRange(),
                    isDiscreteValue = this.series.options.valueAxisType === 'discrete',
                    notInverted = isDiscreteValue && (!businessRange.invertY && !this.rotated || businessRange.invertX && this.rotated) || !isDiscreteValue && this.value > this.minValue && (!businessRange.invertY && !this.rotated || !businessRange.invertX && this.rotated);
                if (!utils.isDefined(maxLabelText) || !utils.isDefined(minLabelText))
                    return;
                this.labelGroup = renderer.createGroup().append(group);
                if (this.options.label.connector && this.options.label.connector.strokeWidth) {
                    this.maxConnector = renderer.createLine(0, 0, 0, 0, this.options.label.connector).append(this.labelGroup);
                    this.minConnector = renderer.createLine(0, 0, 0, 0, this.options.label.connector).append(this.labelGroup)
                }
                this.maxLabelGroup = renderer.createGroup().append(this.labelGroup);
                this.insideMaxLabelGroup = renderer.createGroup().append(this.maxLabelGroup);
                this.minLabelGroup = renderer.createGroup().append(this.labelGroup);
                this.insideMinLabelGroup = renderer.createGroup().append(this.minLabelGroup);
                if (labelOptions.background.fill && labelOptions.background.fill !== 'none' || labelOptions.background.strokeWidth && labelOptions.background.stroke && labelOptions.background.stroke !== 'none') {
                    this.maxLabelBackground = renderer.createRect(this.x, this.y, 0, 0, 0, labelOptions.background).append(this.insideMaxLabelGroup);
                    this.minLabelBackground = renderer.createRect(this.x, this.y, 0, 0, 0, labelOptions.background).append(this.insideMinLabelGroup)
                }
                this.maxLabel = renderer.createText(notInverted ? maxLabelText : minLabelText, this.x, this.y, labelOptions.attributes).append(this.insideMaxLabelGroup);
                this.minLabel = renderer.createText(notInverted ? minLabelText : maxLabelText, this.x, this.y, labelOptions.attributes).append(this.insideMinLabelGroup);
                this.correctLabel();
                this.correctConnectorPosition(this.maxLabelGroup.getBBox(), this.maxConnector);
                this.correctConnectorPosition(this.minLabelGroup.getBBox(), this.minConnector)
            },
            rotateLabel: function() {
                var bboxmax = this.insideMaxLabelGroup.getBBox(),
                    bboxmin = this.insideMinLabelGroup.getBBox(),
                    labelOptions = this.options.label;
                this.insideMaxLabelGroup.applySettings({
                    x: bboxmax.x + bboxmax.width / 2,
                    y: bboxmax.y + bboxmax.height / 2,
                    rotate: labelOptions.rotationAngle
                });
                this.insideMinLabelGroup.applySettings({
                    x: bboxmin.x + bboxmin.width / 2,
                    y: bboxmin.y + bboxmin.height / 2,
                    rotate: labelOptions.rotationAngle
                })
            },
            correctLabelPosition: function() {
                var maxbbox = this.insideMaxLabelGroup.getBBox(),
                    minbbox = this.insideMinLabelGroup.getBBox(),
                    bboxgraphic = this.graphic.getBBox(),
                    x1 = 0,
                    y1 = 0,
                    x2 = 0,
                    y2 = 0;
                if (bboxgraphic.isEmpty)
                    bboxgraphic = this.getGraphicSettings();
                if (this.options.label.position === 'outside')
                    if (!this.rotated) {
                        x1 = x2 += bboxgraphic.width / 2;
                        y1 += bboxgraphic.y - maxbbox.y - maxbbox.height - this.LABEL_OFFSET;
                        y2 += bboxgraphic.y + bboxgraphic.height - minbbox.y + this.LABEL_OFFSET
                    }
                    else {
                        y1 = y2 += bboxgraphic.y - maxbbox.y - maxbbox.height / 2 + bboxgraphic.height / 2;
                        x1 += bboxgraphic.x + bboxgraphic.width - maxbbox.x + this.LABEL_OFFSET;
                        x2 += bboxgraphic.x - minbbox.x - minbbox.width - this.LABEL_OFFSET
                    }
                else if (this.options.label.position === 'inside')
                    if (!this.rotated) {
                        x1 = x2 += bboxgraphic.width / 2;
                        y1 += bboxgraphic.y - maxbbox.y + this.LABEL_OFFSET;
                        y2 += bboxgraphic.y + bboxgraphic.height - minbbox.y - minbbox.height - this.LABEL_OFFSET
                    }
                    else {
                        y1 = y2 += bboxgraphic.y - maxbbox.y - maxbbox.height / 2 + bboxgraphic.height / 2;
                        x1 += bboxgraphic.x + bboxgraphic.width - maxbbox.x - maxbbox.width - this.LABEL_OFFSET;
                        x2 += bboxgraphic.x - minbbox.x + this.LABEL_OFFSET
                    }
                x1 += this.options.label.horizontalOffset;
                y1 += this.options.label.verticalOffset;
                x2 += this.options.label.horizontalOffset;
                y2 += this.options.label.verticalOffset;
                this.checkLabelPosition(x1, y1, x2, y2)
            },
            checkLabelPosition: function(x1, y1, x2, y2) {
                var maxgroupbbox = this.insideMaxLabelGroup.getBBox(),
                    mingroupbbox = this.insideMinLabelGroup.getBBox(),
                    newMaxbbox = {},
                    newMinbbox = {},
                    bboxgraphic = this.graphic.getBBox(),
                    maxX = maxgroupbbox.x + x1,
                    maxY = maxgroupbbox.y + y1,
                    minX = mingroupbbox.x + x2,
                    minY = mingroupbbox.y + y2;
                var visibleArea = this.translator.getCanvasVisibleArea();
                if (visibleArea.minX <= bboxgraphic.x + bboxgraphic.width && visibleArea.maxX >= bboxgraphic.x && visibleArea.minY <= bboxgraphic.y + bboxgraphic.height && visibleArea.maxY >= bboxgraphic.y) {
                    if (!this.rotated) {
                        if (visibleArea.minX > maxX && this.adjustSeriesLabels)
                            x1 += visibleArea.minX - maxX;
                        if (visibleArea.minX > minX && this.adjustSeriesLabels)
                            x2 += visibleArea.minX - minX;
                        if (visibleArea.maxX < maxX + maxgroupbbox.width && this.adjustSeriesLabels)
                            x1 -= maxX + maxgroupbbox.width - visibleArea.maxX;
                        if (visibleArea.maxX < minX + mingroupbbox.width && this.adjustSeriesLabels)
                            x2 -= minX + mingroupbbox.width - visibleArea.maxX;
                        if (visibleArea.minY > maxY)
                            y1 += visibleArea.minY - maxY;
                        if (visibleArea.maxY < minY + mingroupbbox.height)
                            y2 -= minY + mingroupbbox.height - visibleArea.maxY;
                        newMaxbbox.y = maxgroupbbox.y + y1;
                        newMinbbox.y = mingroupbbox.y + y2;
                        if (newMaxbbox.y + maxgroupbbox.height > newMinbbox.y) {
                            y1 -= (newMaxbbox.y + maxgroupbbox.height - newMinbbox.y) / 2;
                            y2 += (newMaxbbox.y + maxgroupbbox.height - newMinbbox.y) / 2;
                            newMaxbbox.y = maxgroupbbox.y + y1;
                            newMinbbox.y = mingroupbbox.y + y2;
                            if (visibleArea.minY > newMaxbbox.y) {
                                y2 += visibleArea.minY - newMaxbbox.y;
                                y1 += visibleArea.minY - newMaxbbox.y
                            }
                            else if (visibleArea.maxY < newMinbbox.y + mingroupbbox.height) {
                                y1 -= newMinbbox.y + mingroupbbox.height - visibleArea.maxY;
                                y2 -= newMinbbox.y + mingroupbbox.height - visibleArea.maxY
                            }
                        }
                    }
                    if (this.rotated) {
                        if (visibleArea.minX > minX)
                            x2 += visibleArea.minX - minX;
                        if (visibleArea.maxX < maxX + maxgroupbbox.width)
                            x1 -= maxX + maxgroupbbox.width - visibleArea.maxX;
                        if (visibleArea.minY > minY && this.adjustSeriesLabels)
                            y2 += visibleArea.minY - minY;
                        if (visibleArea.minY > maxY && this.adjustSeriesLabels)
                            y1 += visibleArea.minY - maxY;
                        if (visibleArea.maxY < minY + mingroupbbox.height && this.adjustSeriesLabels)
                            y2 -= minY + mingroupbbox.height - visibleArea.maxY;
                        if (visibleArea.maxY < maxY + maxgroupbbox.height && this.adjustSeriesLabels)
                            y1 -= maxY + maxgroupbbox.height - visibleArea.maxY;
                        newMaxbbox.x = maxgroupbbox.x + x1;
                        newMinbbox.x = mingroupbbox.x + x2;
                        if (newMaxbbox.x < newMinbbox.x + mingroupbbox.width) {
                            x1 += (newMinbbox.x + mingroupbbox.width - newMaxbbox.x) / 2;
                            x2 -= (newMinbbox.x + mingroupbbox.width - newMaxbbox.x) / 2;
                            newMaxbbox.x = maxgroupbbox.x + x1;
                            newMinbbox.x = mingroupbbox.x + x2;
                            if (visibleArea.minX > newMinbbox.x) {
                                x2 += visibleArea.minX - newMinbbox.x;
                                x1 += visibleArea.minX - newMinbbox.x
                            }
                            else if (visibleArea.maxX < newMaxbbox.x + maxgroupbbox.width) {
                                x1 -= newMaxbbox.x + maxgroupbbox.width - visibleArea.maxX;
                                x2 -= newMaxbbox.x + maxgroupbbox.width - visibleArea.maxX
                            }
                        }
                    }
                }
                this.insideMaxLabelGroup.move(~~x1, ~~y1);
                this.insideMinLabelGroup.move(~~x2, ~~y2)
            },
            correctBackgroundPosition: function() {
                if (!this.maxLabelBackground || !this.minLabelBackground)
                    return;
                var maxbbox = this.maxLabel.getBBox(),
                    minbbox = this.minLabel.getBBox(),
                    x1 = maxbbox.x - this.LABEL_BACKGROUND_PADDING_X,
                    x2 = minbbox.x - this.LABEL_BACKGROUND_PADDING_X,
                    y1 = maxbbox.y - this.LABEL_BACKGROUND_PADDING_Y,
                    y2 = minbbox.y - this.LABEL_BACKGROUND_PADDING_Y,
                    width1 = maxbbox.width + 2 * this.LABEL_BACKGROUND_PADDING_X,
                    width2 = minbbox.width + 2 * this.LABEL_BACKGROUND_PADDING_X,
                    height1 = maxbbox.height + 2 * this.LABEL_BACKGROUND_PADDING_Y,
                    height2 = minbbox.height + 2 * this.LABEL_BACKGROUND_PADDING_Y;
                this.maxLabelBackground.applySettings({
                    x: x1,
                    y: y1,
                    width: width1,
                    height: height1
                });
                this.minLabelBackground.applySettings({
                    x: x2,
                    y: y2,
                    width: width2,
                    height: height2
                })
            },
            correctConnectorPosition: function(bbox, connector) {
                if (!connector)
                    return;
                var bboxgraphic = this.graphic.getBBox(),
                    x1,
                    x2,
                    y1,
                    y2,
                    centerLabelY = this.maxLabelBackground || this.minLabelBackground ? bbox.y + bbox.height / 2 : null,
                    centerLabelX = this.maxLabelBackground || this.minLabelBackground ? bbox.x + bbox.width / 2 : null;
                if (bboxgraphic.isEmpty)
                    bboxgraphic = this.getGraphicSettings();
                if (!this.rotated) {
                    if ((centerLabelY || bbox.y + bbox.height) < bboxgraphic.y) {
                        y1 = centerLabelY || bbox.y + bbox.height;
                        y2 = bboxgraphic.y
                    }
                    else if ((centerLabelY || bbox.y) > bboxgraphic.y + bboxgraphic.height) {
                        y1 = centerLabelY || bbox.y;
                        y2 = bboxgraphic.y + bboxgraphic.height
                    }
                    else
                        return false;
                    x1 = Math.round(bbox.x + bbox.width / 2);
                    if (x1 > bboxgraphic.x + bboxgraphic.width)
                        x2 = bboxgraphic.x + bboxgraphic.width;
                    else if (x1 < bboxgraphic.x)
                        x2 = bboxgraphic.x;
                    else
                        x2 = x1
                }
                else {
                    if ((centerLabelX || bbox.x) > bboxgraphic.x + bboxgraphic.width) {
                        x1 = centerLabelX || bbox.x;
                        x2 = bboxgraphic.x + bboxgraphic.width
                    }
                    else if ((centerLabelX || bbox.x + bbox.width) < bboxgraphic.x) {
                        x1 = centerLabelX || bbox.x + bbox.width;
                        x2 = bboxgraphic.x
                    }
                    else
                        return false;
                    y1 = Math.round(bbox.y + bbox.height / 2);
                    if (y1 > bboxgraphic.y + bboxgraphic.height)
                        y2 = bboxgraphic.y + bboxgraphic.height;
                    else if (y1 < bboxgraphic.y)
                        y2 = bboxgraphic.y;
                    else
                        y2 = y1
                }
                connector.applySettings({points: [x1, y1, x2, y2]})
            },
            getTooltipFormatObject: function(tooltip) {
                var minValue = tooltip.formatValueTooltip.call({value: this.initialMinValue}, tooltip.options),
                    value = tooltip.formatValueTooltip.call({value: this.initialValue}, tooltip.options);
                return {
                        argument: this.initialArgument,
                        valueText: minValue + ' - ' + value,
                        rangeValue1Text: minValue,
                        rangeValue2Text: value,
                        rangeValue1: this.initialMinValue,
                        rangeValue2: this.initialValue,
                        seriesName: this.options.seriesName,
                        point: this,
                        originalMinValue: this.originalMinValue,
                        originalValue: this.originalValue,
                        originalArgument: this.originalArgument
                    }
            },
            hasValue: function() {
                return this.initialValue !== null && this.initialMinValue !== null
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file bubblePoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            statesConsts = series.consts.states,
            formatHelper = DX.formatHelper,
            BasePoint = series.BasePoint;
        var BubblePoint = BasePoint.inherit({
                ctor: function(data) {
                    this.callBase(data);
                    this.size = this.initialSize = data.size;
                    this.labelFormatObject.size = this.initialSize
                },
                correctCoordinates: function(radius) {
                    this.bubbleSize = radius
                },
                drawMarker: function(renderer, group, animationEnabled) {
                    if (!this.hasValue())
                        return;
                    var marker = renderer.createCircle(this.x, this.y, this.bubbleSize, this.options.attributes).append(group);
                    this.graphic = marker;
                    this._checkState();
                    if (animationEnabled)
                        this.graphic.applySettings({
                            scale: {
                                x: 0.01,
                                y: 0.01
                            },
                            translateX: this.x,
                            translateY: this.y
                        })
                },
                drawTrackerMarker: function(renderer, trackerGroup) {
                    if (!this.hasValue())
                        return;
                    var point = this,
                        options = point.options,
                        trackerCircle = renderer.createCircle(point.x, point.y, point.bubbleSize, point._trackerAttrs);
                    trackerCircle.append(trackerGroup);
                    trackerCircle.data({point: this})
                },
                getTooltipCoords: function() {
                    if (this.graphic)
                        return {
                                x: this.x,
                                y: this.y,
                                offset: 0
                            }
                },
                correctLabelPosition: function() {
                    if (this.options.label.position === 'outside')
                        this.callBase();
                    else {
                        var bbox = this.insideLabelGroup.getBBox(),
                            bboxgraphic = this.graphic ? this.graphic.getBBox() : {
                                x: this.x,
                                y: this.y,
                                height: 0,
                                width: 0
                            },
                            x = 0,
                            y = 0;
                        if (bboxgraphic.isEmpty)
                            bboxgraphic = {
                                x: this.x,
                                y: this.y,
                                height: 0,
                                width: 0
                            };
                        y += bboxgraphic.y + bboxgraphic.height / 2 - bbox.y - bbox.height / 2;
                        x += this.options.label.horizontalOffset;
                        y += this.options.label.verticalOffset;
                        this.checkLabelPosition({
                            x: bbox.x + x,
                            y: bbox.y + y,
                            height: bbox.height,
                            width: bbox.width
                        }, x, y)
                    }
                },
                applyNormalStyle: function() {
                    if (this.graphic) {
                        var normal = $.extend(true, {}, this.options.states.normal);
                        delete normal.opacity;
                        this.graphic.applySettings(normal)
                    }
                    return this
                },
                animate: function(complete) {
                    if (!this.graphic) {
                        complete && complete();
                        return
                    }
                    this.graphic.animate({
                        scale: {
                            x: 1,
                            y: 1
                        },
                        translate: {
                            x: 0,
                            y: 0
                        }
                    }, {}, complete)
                }
            });
        series.BubblePoint = BubblePoint
    })(jQuery, DevExpress);
    /*! Module viz-core, file pointFactory.js */
    (function($, DX) {
        var series = DX.viz.charts.series;
        series.pointFactory = {createPoint: function(seriesType, pointOptions) {
                seriesType = (seriesType || '').toLowerCase();
                switch (seriesType) {
                    case'line':
                        return new series.BasePoint(pointOptions);
                    case'stackedline':
                        return new series.BasePoint(pointOptions);
                    case'fullstackedline':
                        return new series.BasePoint(pointOptions);
                    case'area':
                        return new series.BasePoint(pointOptions);
                    case'stackedarea':
                        return new series.BasePoint(pointOptions);
                    case'fullstackedarea':
                        return new series.BasePoint(pointOptions);
                    case'bar':
                        return new series.BarPoint(pointOptions);
                    case'stackedbar':
                        return new series.BarPoint(pointOptions);
                    case'fullstackedbar':
                        return new series.BarPoint(pointOptions);
                    case'spline':
                        return new series.BasePoint(pointOptions);
                    case'splinearea':
                        return new series.BasePoint(pointOptions);
                    case'scatter':
                        return new series.BasePoint(pointOptions);
                    case'candlestick':
                        return new series.OhlcPoint(pointOptions);
                    case'stock':
                        return new series.StockPoint(pointOptions);
                    case'rangearea':
                        return new series.RangePoint(pointOptions);
                    case'rangesplinearea':
                        return new series.RangePoint(pointOptions);
                    case'rangebar':
                        return new series.RangeBarPoint(pointOptions);
                    case'pie':
                        return new series.PiePoint(pointOptions);
                    case'doughnut':
                        return new series.PiePoint(pointOptions);
                    case'stepline':
                        return new series.BasePoint(pointOptions);
                    case'steparea':
                        return new series.BasePoint(pointOptions);
                    case'bubble':
                        return new series.BubblePoint(pointOptions);
                    default:
                        return null
                }
            }}
    })(jQuery, DevExpress);
    /*! Module viz-core, file baseSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            eventsConsts = series.consts.events,
            statesConsts = series.consts.states,
            utils = DX.utils,
            core = DX.viz.core,
            ParseUtils = core.ParseUtils,
            SERIES_VALUE_MARGIN_PRIORITY = 20,
            FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY = 15,
            SERIES_LABEL_VALUE_MARGIN = 0.3,
            ALL_SERIES_POINTS_MODE = 'allseriespoints',
            INCLUDE_POINTS_MODE = 'includepoints',
            HOVER_CHECK = 0,
            SELECTION_CHECK = 1,
            BAR_ZERO_VALUE_MARGIN_PRIORITY = 20;
        series.BaseSeries = DX.Class.inherit({
            ctor: function(renderer, options, isRangeSeries) {
                var _this = this;
                _this.type = options.specificType || 'unknown';
                _this.isRangeSeries = isRangeSeries;
                _this.renderer = renderer;
                _this.isIE8 = DX.browser.msie && DX.browser.version < 9;
                _this.points = [];
                _this.originalPoints = [];
                _this._parseOptions(options);
                _this._parsedUserOptions = $.extend(true, {}, options);
                _this.userOptions = options;
                _this.tag = options.tag
            },
            dispose: function() {
                var _this = this;
                _this.off();
                $.each(_this.points || [], function(_, point) {
                    point.dispose()
                });
                _this.points = null;
                $.each(_this.trackerElements || [], function(_, tracker) {
                    tracker.removeData()
                });
                _this.trackerElements = null;
                _this.hoverPattern = null;
                _this.selectedPattern = null;
                _this.seriesGroup = null;
                _this.pointsByArgument = null;
                _this.segments = null;
                _this.preparedSegments = null;
                _this.renderer = null;
                _this._rawData = null;
                _this._parsedUserOptions = null;
                _this.options = null;
                _this.userOptions = null;
                _this.tag = null;
                _this.rangeData = null;
                _this.translator = null;
                _this.styles = null;
                _this.legend = null;
                if (_this.markerPatterns) {
                    $.each(_this.markerPatterns, function(_, p) {
                        p.dispose && p.dispose()
                    });
                    _this.markerPatterns = null
                }
            },
            getRangeData: function(visibleRange, calcInterval) {
                var self = this,
                    options = self.options,
                    argumentCategories = options.argumentCategories,
                    discreteArgumentAxis = options.argumentAxisType === 'discrete',
                    argumentType = options.argumentType,
                    valueCategories = options.valueCategories,
                    discreteValueAxis = options.valueAxisType === 'discrete',
                    valueType = options.valueType,
                    rangeData = {
                        visibleValCategories: [],
                        categoriesVal: [],
                        categoriesArg: []
                    },
                    points = self.points,
                    pointsLength = points && points.length,
                    lastVisibleIndex,
                    intervalVal,
                    intervalArg;
                function addToVisibleVal(val) {
                    if (discreteValueAxis) {
                        if ($.inArray(val, rangeData.visibleValCategories) === -1)
                            rangeData.visibleValCategories.push(val)
                    }
                    else {
                        if (val < rangeData.minVisibleVal || !utils.isDefined(rangeData.minVisibleVal))
                            rangeData.minVisibleVal = val;
                        if (val > rangeData.maxVisibleVal || !utils.isDefined(rangeData.maxVisibleVal))
                            rangeData.maxVisibleVal = val
                    }
                }
                var processArgument = function(arg, prevArg) {
                        var interval;
                        if (arg < rangeData.minArg || !utils.isDefined(rangeData.minArg))
                            rangeData.minArg = arg;
                        if (arg > rangeData.maxArg || !utils.isDefined(rangeData.maxArg))
                            rangeData.maxArg = arg;
                        if (utils.isDefined(prevArg))
                            interval = Math.abs(calcInterval ? calcInterval(arg, prevArg) : arg - prevArg);
                        if (utils.isDefined(interval) && (interval < rangeData.minIntervalArg || !utils.isDefined(rangeData.minIntervalArg)))
                            rangeData.minIntervalArg = interval
                    };
                var processValue = function(val, minVal, prevVal, prevMinVal) {
                        var interval;
                        if (val < rangeData.minVal || !utils.isDefined(rangeData.minVal))
                            rangeData.minVal = val;
                        if (val > rangeData.maxVal || !utils.isDefined(rangeData.maxVal))
                            rangeData.maxVal = val;
                        if (self.isRangeSeries) {
                            if (minVal < rangeData.minVal || !utils.isDefined(rangeData.minVal))
                                rangeData.minVal = minVal;
                            if (minVal > rangeData.maxVal || !utils.isDefined(rangeData.maxVal))
                                rangeData.maxVal = minVal
                        }
                        if (utils.isDefined(prevVal))
                            interval = Math.abs(val - prevVal);
                        if (self.isRangeSeries && utils.isDefined(prevMinVal))
                            interval = Math.min(interval, Math.abs(minVal - prevMinVal));
                        if (utils.isDefined(interval) && (interval < rangeData.minIntervalVal || !utils.isDefined(rangeData.minIntervalVal)))
                            rangeData.minIntervalVal = interval
                    };
                function unique(array, field) {
                    var values = {};
                    return $.map(array, function(item) {
                            var value = item[field];
                            var result = !values[value] ? value : null;
                            values[value] = true;
                            return result
                        })
                }
                if (discreteArgumentAxis) {
                    rangeData.categoriesArg = unique(points, 'argument');
                    processArgument = $.noop
                }
                if (discreteValueAxis) {
                    rangeData.categoriesVal = unique(points, 'value');
                    processValue = $.noop
                }
                if (pointsLength) {
                    $.each(points, function(i, point) {
                        var prevPoint,
                            val = point.value,
                            minVal = point.minValue,
                            arg = point.argument,
                            prevVal,
                            prevMinVal,
                            prevArg;
                        if (i !== 0) {
                            prevPoint = points[i - 1];
                            prevVal = prevPoint.value;
                            prevMinVal = prevPoint.minValue;
                            prevArg = prevPoint.argument
                        }
                        if (point.hasValue())
                            processValue(val, minVal, prevVal, prevMinVal);
                        processArgument(arg, prevArg);
                        if (discreteArgumentAxis || !visibleRange || arg < visibleRange.minArg || arg > visibleRange.maxArg)
                            return;
                        if (!utils.isDefined(rangeData.minVisibleVal) && i)
                            if (prevPoint.hasValue()) {
                                addToVisibleVal(prevVal);
                                if (self.isRangeSeries)
                                    addToVisibleVal(prevMinVal)
                            }
                        if (point.hasValue()) {
                            lastVisibleIndex = i;
                            addToVisibleVal(val);
                            if (self.isRangeSeries)
                                addToVisibleVal(minVal)
                        }
                    });
                    if (utils.isDefined(lastVisibleIndex) && lastVisibleIndex < pointsLength - 1)
                        if (points[lastVisibleIndex + 1].hasValue()) {
                            addToVisibleVal(points[lastVisibleIndex + 1].value);
                            if (self.isRangeSeries)
                                addToVisibleVal(points[lastVisibleIndex + 1].minValue)
                        }
                    if (!self.options.rotated) {
                        if (utils.isDefined(rangeData.minVal)) {
                            rangeData.minY = rangeData.minVal;
                            rangeData.maxY = rangeData.maxVal;
                            rangeData.intervalY = undefined
                        }
                        if (utils.isDefined(rangeData.minArg)) {
                            rangeData.minX = rangeData.minArg;
                            rangeData.maxX = rangeData.maxArg;
                            rangeData.intervalX = rangeData.minIntervalArg
                        }
                        if (rangeData.categoriesArg.length)
                            rangeData.categoriesX = rangeData.categoriesArg.slice(0);
                        if (rangeData.categoriesVal.length)
                            rangeData.categoriesY = rangeData.categoriesVal.slice(0);
                        if (rangeData.visibleValCategories.length)
                            rangeData.visibleCategoriesY = rangeData.visibleValCategories.slice(0);
                        rangeData.minVisibleY = rangeData.minVisibleVal;
                        rangeData.maxVisibleY = rangeData.maxVisibleVal
                    }
                    else {
                        if (utils.isDefined(rangeData.minVal)) {
                            rangeData.minX = rangeData.minVal;
                            rangeData.maxX = rangeData.maxVal;
                            rangeData.intervalX = undefined
                        }
                        if (utils.isDefined(rangeData.minArg)) {
                            rangeData.minY = rangeData.minArg;
                            rangeData.maxY = rangeData.maxArg;
                            rangeData.intervalY = rangeData.minIntervalArg
                        }
                        if (rangeData.categoriesArg.length)
                            rangeData.categoriesY = rangeData.categoriesArg.slice(0);
                        if (rangeData.categoriesVal.length)
                            rangeData.categoriesX = rangeData.categoriesVal.slice(0);
                        if (rangeData.visibleValCategories.length)
                            rangeData.visibleCategoriesX = rangeData.visibleValCategories.slice(0);
                        rangeData.minVisibleX = rangeData.minVisibleVal;
                        rangeData.maxVisibleX = rangeData.maxVisibleVal
                    }
                }
                delete rangeData.minArg;
                delete rangeData.maxArg;
                delete rangeData.minVal;
                delete rangeData.maxVal;
                delete rangeData.minIntervalArg;
                delete rangeData.minIntervalVal;
                delete rangeData.minVisibleVal;
                delete rangeData.maxVisibleVal;
                delete rangeData.visibleValCategories;
                delete rangeData.categoriesArg;
                delete rangeData.categoriesVal;
                rangeData = this.addLabelPaddingsToRange(rangeData);
                rangeData = this.processRangeForFullStackedSeries(rangeData);
                this.rangeData = rangeData;
                rangeData = this.getRangeMinValue(rangeData);
                return rangeData
            },
            getRangeMinValue: function(range) {
                if (this.type.slice(-3) === "bar" || this.type.slice(-4) === "area") {
                    if (!range)
                        return range;
                    if (this.isRangeSeries)
                        return range;
                    if (!this.options.rotated)
                        range.keepValueMarginsX = true;
                    else
                        range.keepValueMarginsY = true;
                    if (range.minY !== undefined && !this.options.rotated && this.options.valueAxisType !== 'logarithmic') {
                        range.minY = range.minY > 0 ? 0 : range.minY;
                        this.setZeroPadding(range, range.minY, 'minValueMarginY');
                        range.maxY = range.maxY < 0 ? 0 : range.maxY;
                        if (range.maxY === 0 || range.maxY > 0 && range.minY < 0) {
                            range.minValueMarginY = range.maxValueMarginY;
                            range.minValueMarginYPriority = range.maxValueMarginYPriority
                        }
                        this.setZeroPadding(range, range.maxY, 'maxValueMarginY')
                    }
                    else if (range.minX !== undefined && this.options.rotated && this.options.valueAxisType !== 'logarithmic') {
                        range.minX = range.minX > 0 ? 0 : range.minX;
                        this.setZeroPadding(range, range.minX, 'minValueMarginX');
                        range.maxX = range.maxX < 0 ? 0 : range.maxX;
                        if (range.maxX === 0 || range.maxX > 0 && range.minX < 0) {
                            range.minValueMarginX = range.maxValueMarginX;
                            range.minValueMarginXPriority = range.maxValueMarginXPriority
                        }
                        this.setZeroPadding(range, range.maxX, 'maxValueMarginX')
                    }
                }
                return range
            },
            setZeroPadding: function(range, val, prefix) {
                if (val === 0)
                    this.setPadding(range, prefix, 0, BAR_ZERO_VALUE_MARGIN_PRIORITY)
            },
            setPadding: function(range, prefix, val, priority) {
                range[prefix] = val;
                range[prefix + 'Priority'] = priority
            },
            addLabelPaddingsToRange: function(rangeData) {
                var series = this;
                if (series.areLabelsVisible() && series.styles.point.label.position !== 'inside')
                    if (!series.options.rotated) {
                        this.setPadding(rangeData, 'maxValueMarginY', SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY);
                        if (series.isRangeSeries)
                            this.setPadding(rangeData, 'minValueMarginY', SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY)
                    }
                    else {
                        this.setPadding(rangeData, 'maxValueMarginX', SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY);
                        if (series.isRangeSeries)
                            this.setPadding(rangeData, 'minValueMarginX', SERIES_LABEL_VALUE_MARGIN, SERIES_VALUE_MARGIN_PRIORITY)
                    }
                return rangeData
            },
            isFullStackedSeries: function() {
                return this.type.indexOf('fullstacked') === 0
            },
            isStackedSeries: function() {
                return this.type.indexOf('stacked') === 0
            },
            processRangeForFullStackedSeries: function(rangeData) {
                var self = this,
                    indentName,
                    isRangeEmpty = $.isEmptyObject(rangeData);
                if (self.isFullStackedSeries())
                    if (!self.options.rotated) {
                        self.setPadding(rangeData, 'minValueMarginY', 0, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY);
                        self.setPadding(rangeData, 'maxValueMarginY', 0, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY);
                        !isRangeEmpty && (rangeData.minY = 0)
                    }
                    else {
                        self.setPadding(rangeData, 'minValueMarginX', 0, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY);
                        self.setPadding(rangeData, 'maxValueMarginX', 0, FULLSTACKED_SERIES_VALUE_MARGIN_PRIORITY);
                        !isRangeEmpty && (rangeData.minX = 0)
                    }
                return rangeData
            },
            _applyClippings: function(seriesElementsOptions, seriesMarkersOptions, labelsGroupOptions) {
                if (this.paneClipRectID) {
                    seriesElementsOptions.clipId = this.paneClipRectID;
                    labelsGroupOptions.clipId = this.paneClipRectID;
                    if (this.forceClipping)
                        seriesMarkersOptions.clipId = this.paneClipRectID
                }
            },
            _applyTrackersClippings: function() {
                var _this = this,
                    options = _this.options;
                if (_this.paneClipRectID) {
                    options.seriesTrackerGroup.applySettings({clipId: _this.paneClipRectID});
                    if (_this.forceClipping)
                        options.markerTrackerGroup.applySettings({clipId: _this.paneClipRectID})
                }
            },
            _drawTrackersForSegment: function(index, segment) {
                this.drawPointTrackers(segment)
            },
            drawTrackers: function() {
                var _this = this;
                if (!_this.segments)
                    return;
                _this.trackerElements = [];
                $.each(_this.segments, function(index, segment) {
                    _this._drawTrackersForSegment(index, segment)
                });
                _this._applyTrackersClippings()
            },
            draw: function(translator, animationEnabled) {
                var seriesContainerOptions = {'class': 'dxc-series'},
                    seriesElementsOptions = {'class': 'dxc-elements'},
                    seriesMarkersOptions = $.extend({'class': 'dxc-markers'}, this.styles.point.states.normal),
                    labelsGroupOptions = {'class': 'dxc-series-labels'},
                    seriesElementsGroup,
                    seriesMarkersGroup,
                    labelsGroup;
                if (!translator) {
                    throw new Error('Translator was not initialized before call Series Draw()');
                    return
                }
                this.translator = translator;
                this._translateCoors();
                this._applyClippings(seriesElementsOptions, seriesMarkersOptions, labelsGroupOptions);
                if (!this.seriesGroup)
                    this.seriesGroup = this.renderer.createGroup(seriesContainerOptions);
                else
                    this.seriesGroup.clear();
                seriesElementsGroup = this.renderer.createGroup(seriesElementsOptions).append(this.seriesGroup);
                seriesMarkersGroup = this.renderer.createGroup(seriesMarkersOptions).append(this.seriesGroup);
                this.seriesGroup.append(this.options.seriesGroup);
                labelsGroup = this.renderer.createGroup(labelsGroupOptions).append(this.options.seriesLabelsGroup);
                this.createPatterns();
                this.drawSeriesData(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled);
                if (this.isSelected())
                    this.setSelectedState(this.lastSelectionMode);
                else if (this.isHovered())
                    this.setHoverState(this.lastHoverdMode);
                else
                    this.fullState = statesConsts.normalMark;
                return this
            },
            createPatterns: function() {
                var self = this,
                    hover = self.styles.states.hover,
                    selected = self.styles.states.selected;
                if (!self.hoverPatternColor) {
                    self.hoverPatternColor = hover.fill;
                    self.selectedPatternColor = selected.fill
                }
                if (!self.hoverPattern) {
                    self.hoverPattern = self.renderer.createPattern(self.hoverPatternColor, hover.hatching);
                    self.selectedPattern = self.renderer.createPattern(self.selectedPatternColor, selected.hatching)
                }
                self.hoverPattern.append();
                self.selectedPattern.append();
                self.styles.pointStyles = self.styles.pointStyles || [];
                $.each(self.styles.pointStyles, function(_, style) {
                    if (style) {
                        var pointHover = style.states.hover,
                            pointSelected = style.states.selected;
                        if (!style.hoverPatternColor) {
                            style.hoverPatternColor = pointHover.fill;
                            style.selectedPatternColor = pointSelected.fill
                        }
                        if (!style.hoverPattern) {
                            style.hoverPattern = self.renderer.createPattern(style.hoverPatternColor, pointHover.hatching);
                            style.selectedPattern = self.renderer.createPattern(style.selectedPatternColor, pointSelected.hatching)
                        }
                        style.hoverPattern.append();
                        style.selectedPattern.append()
                    }
                })
            },
            areLabelsVisible: function() {
                var series = this;
                return series.styles.point.label.visible && (!utils.isDefined(series.styles.maxLabelCount) || series.points.length <= series.styles.maxLabelCount)
            },
            getPoints: function() {
                return this.points
            },
            getOriginalPoints: function() {
                return this.originalPoints
            },
            getValueFields: function() {
                var _this = this;
                return _this.isRangeSeries ? [_this.options.rangeValue1Field, _this.options.rangeValue2Field] : [_this.options.valueField]
            },
            getTeamplatedFields: function() {
                var _this = this,
                    fields = this.getValueFields(),
                    teampleteFields = [];
                fields.push(this.getTagField());
                $.each(fields, function(_, field) {
                    var fieldsObject = {};
                    fieldsObject.teamplateField = field + _this.name;
                    fieldsObject.originalField = field;
                    teampleteFields.push(fieldsObject)
                });
                return teampleteFields
            },
            getArgumentField: function() {
                return this.options.argumentField
            },
            getTagField: function() {
                return this.options.tagField
            },
            updateTeamplateFieldNames: function() {
                var _this = this;
                if (_this.isRangeSeries) {
                    _this.options.rangeValue1Field = _this.options.rangeValue1Field + _this.name;
                    _this.options.rangeValue2Field = _this.options.rangeValue2Field + _this.name
                }
                else
                    _this.options.valueField = _this.options.valueField + _this.name;
                _this.options.tagField = _this.options.tagField + _this.name
            },
            _updateDataType: function(options) {
                var _this = this;
                _this.options.argumentType = options.argumentType;
                _this.options.valueType = options.valueType;
                _this.options.argumentAxisType = options.argumentAxisType;
                _this.options.valueAxisType = options.valueAxisType
            },
            select: function() {
                this.options.seriesGroup && this.options.seriesGroup.trigger(new $.Event(eventsConsts.selectSeries, {target: this}), this.options.selectionMode);
                this.seriesGroup && this.seriesGroup.toForeground();
                if (this.trackerElements && this.trackerElements.length)
                    $.each(this.trackerElements, function(_, element) {
                        element.toBackground()
                    })
            },
            clearSelection: function clearSelection() {
                this.options.seriesGroup && this.options.seriesGroup.trigger(new $.Event(eventsConsts.deselectSeries, {target: this}), this.options.selectionMode)
            },
            selectPoint: function(point) {
                this.options.seriesGroup && this.options.seriesGroup.trigger(new $.Event(eventsConsts.selectPoint), point)
            },
            deselectPoint: function(point) {
                this.options.seriesGroup && this.options.seriesGroup.trigger(new $.Event(eventsConsts.deselectPoint), point)
            },
            showPointTooltip: function(point) {
                this.options.seriesGroup && this.options.seriesGroup.trigger(new $.Event(eventsConsts.showPointTooltip), point)
            },
            hidePointTooltip: function(point) {
                this.options.seriesGroup && this.options.seriesGroup.trigger(new $.Event(eventsConsts.hidePointTooltip), point)
            },
            getAllPoints: function() {
                return this.originalPoints.slice()
            },
            getPointByPos: function(pos) {
                return this.points && this.points[pos]
            },
            getPointByArg: function(arg) {
                return this.pointsByArgument[arg.valueOf()] || null
            },
            on: function(events, data, handler) {
                $(this).on(events, data, handler);
                return this
            },
            off: function(events) {
                $(this).off(events);
                return this
            },
            setHoverState: function(mode) {
                this.fullState = this.fullState | statesConsts.hoverMark;
                mode = mode || this.options.hoverMode;
                this.lastHoverMode = mode;
                if (!this._checkBehavior(mode, HOVER_CHECK))
                    return;
                this.applyHoverStyle(mode);
                if (this.legend)
                    this.legend.applyHoverStyle(this)
            },
            releaseHoverState: function() {
                var mode = this.lastHoverMode || this.options.hoverMode;
                this.fullState = this.fullState & ~statesConsts.hoverMark;
                delete this.lastHoverMode;
                if (!this._checkBehavior(mode, HOVER_CHECK))
                    return;
                this.applyNormalStyle(mode);
                if (this.legend)
                    this.legend.applyNormalStyle(this)
            },
            setSelectedState: function(mode) {
                this.fullState = this.fullState | statesConsts.selectedMark;
                this.lastSelectionMode = mode;
                if (!this._checkBehavior(mode, SELECTION_CHECK))
                    return;
                if (this.lastHoverMode === ALL_SERIES_POINTS_MODE || this.lastHoverMode === INCLUDE_POINTS_MODE)
                    this.applyNormalStyle(INCLUDE_POINTS_MODE);
                mode = mode || this.options.selectionMode;
                this.applySelectionStyle(mode);
                if (this.legend)
                    this.legend.applySelectionStyle(this)
            },
            releaseSelectedState: function() {
                var mode = this.lastSelectionMode || this.options.selectionMode;
                this.fullState = this.fullState & ~statesConsts.selectedMark;
                if (!this._checkBehavior(mode, SELECTION_CHECK))
                    return;
                if (this.isHovered()) {
                    if ((mode === INCLUDE_POINTS_MODE || mode === ALL_SERIES_POINTS_MODE) && (this.lastHoverMode !== INCLUDE_POINTS_MODE || this.lastHoverMode === ALL_SERIES_POINTS_MODE)) {
                        this.applyNormalStyle(mode);
                        if (this.legend)
                            this.legend.applyNormalStyle(this)
                    }
                    this.applyHoverStyle(this.lastHoverMode);
                    if (this.legend)
                        this.legend.applyHoverStyle(this)
                }
                else {
                    this.applyNormalStyle(mode);
                    if (this.legend)
                        this.legend.applyNormalStyle(this)
                }
                delete this.lastSelectionMode
            },
            _checkBehavior: function(mode, behavior) {
                if (mode === 'none')
                    return false;
                switch (behavior) {
                    case HOVER_CHECK:
                        if (!this.isSelected() || this.options.selectionMode === 'none')
                            return true;
                        return false;
                    case SELECTION_CHECK:
                        return true
                }
                return false
            },
            setPointHoverState: function(point) {
                point.fullState = point.fullState | statesConsts.hoverMark;
                if (!(this.isSelected() && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS_MODE)) && !point.isSelected())
                    point.applyHoverStyle()
            },
            releasePointHoverState: function(point) {
                point.fullState = point.fullState & ~statesConsts.hoverMark;
                if (!(this.isSelected() && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS_MODE)) && !point.isSelected())
                    if (!(this.isHovered() && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS_MODE)))
                        point.applyNormalStyle()
            },
            setPointSelectedState: function(point) {
                point.fullState = point.fullState | statesConsts.selectedMark;
                point.applySelectionStyle()
            },
            releasePointSelectedState: function(point) {
                point.fullState = point.fullState & ~statesConsts.selectedMark;
                if (this.isHovered() && (this.lastHoverMode === ALL_SERIES_POINTS_MODE || this.lastHoverMode === INCLUDE_POINTS_MODE) || point.isHovered())
                    point.applyHoverStyle();
                else if (this.isSelected() && (this.lastSelectionMode === ALL_SERIES_POINTS_MODE || this.lastSelectionMode === INCLUDE_POINTS_MODE))
                    point.applySelectionStyle();
                else
                    point.applyNormalStyle()
            },
            isHovered: function() {
                return !!(this.fullState & statesConsts.hoverMark)
            },
            isSelected: function() {
                return !!(this.fullState & statesConsts.selectedMark)
            },
            _translateCoors: function() {
                var series = this;
                var tr = series.translator;
                $.each(series.points, function(i, p) {
                    p.translate(tr)
                })
            },
            _getTicksForAggregation: function(min, max, screenDelta, pointSize) {
                return core.tickProvider.getTicks({
                        min: min,
                        max: max,
                        screenDelta: screenDelta,
                        gridSpacingFactor: pointSize
                    })
            },
            getStackName: function() {
                if (this.type === 'stackedbar' || this.type === 'fullstackedbar')
                    return this.stackName;
                return null
            },
            resamplePoints: function(translator, min, max) {
                var _this = this,
                    minI,
                    maxI,
                    i;
                if (!_this.getOriginalPoints().length)
                    return;
                $.each(_this.getOriginalPoints(), function(i, point) {
                    minI = point.argument - min <= 0 ? i : minI;
                    if (!maxI)
                        maxI = point.argument - max > 0 ? i : null
                });
                minI = minI ? minI : 1;
                maxI = utils.isDefined(maxI) ? maxI : _this.getOriginalPoints().length - 1;
                min = _this.getOriginalPoints()[minI - 1].argument;
                max = _this.getOriginalPoints()[maxI].argument;
                _this.translator = translator;
                var sizePoint = _this._getPointSize(),
                    ticks;
                if (_this.options.argumentAxisType !== 'discrete' && _this.options.valueAxisType !== 'discrete')
                    ticks = _this._getTicksForAggregation(min, max, _this.translator.width, sizePoint);
                else
                    ticks = _this.translator.width / sizePoint;
                _this.points = _this._resample(ticks, ticks.tickInterval);
                _this._segmentPoints()
            },
            reinitData: function(data) {
                var self = this,
                    createPoint = series.pointFactory.createPoint,
                    rotated = self.options.rotated,
                    pointStyle,
                    i,
                    curPoint,
                    point,
                    valueField,
                    rangeValue1Field,
                    rangeValue2Field,
                    options = self.options,
                    argumentField = options.argumentField,
                    tagField = options.tagField,
                    customizePoint = self.options.customizePoint;
                self.styles.pointStyles = [];
                if (data && data.length)
                    self._canRenderCompleteHandle = true;
                self.pointsByArgument = {};
                self.segments = [];
                self.points = [];
                if (!data)
                    return;
                if (!self.isRangeSeries) {
                    valueField = options.valueField || 'val';
                    for (i = 0; i < data.length; i++) {
                        curPoint = data[i];
                        if (curPoint[argumentField] === null || curPoint[argumentField] === undefined || curPoint[valueField] === undefined)
                            continue;
                        pointStyle = self._getPointStyle(self.styles.point, i, curPoint[argumentField], curPoint[valueField], undefined, curPoint[tagField]);
                        point = createPoint(self.type, {
                            value: curPoint[valueField],
                            argument: curPoint[argumentField],
                            originalValue: curPoint['original' + valueField],
                            originalArgument: curPoint['original' + argumentField],
                            rotated: rotated,
                            options: pointStyle,
                            tag: curPoint[tagField],
                            series: self
                        });
                        self.points.push(point);
                        self.pointsByArgument[point.argument.valueOf()] = self.pointsByArgument[point.argument.valueOf()] || point
                    }
                }
                else {
                    rangeValue1Field = options.rangeValue1Field || 'val1';
                    rangeValue2Field = options.rangeValue2Field || 'val2';
                    for (i = 0; i < data.length; i++) {
                        curPoint = data[i];
                        if (curPoint[argumentField] === null || curPoint[argumentField] === undefined || curPoint[rangeValue1Field] === undefined || curPoint[rangeValue2Field] === undefined)
                            continue;
                        pointStyle = self._getPointStyle(self.styles.point, i, curPoint[argumentField], curPoint[rangeValue1Field], curPoint[rangeValue2Field], curPoint[tagField]);
                        point = createPoint(self.type, {
                            minValue: curPoint[rangeValue1Field],
                            value: curPoint[rangeValue2Field],
                            argument: curPoint[argumentField],
                            originalMinValue: curPoint['original' + rangeValue1Field],
                            originalValue: curPoint['original' + rangeValue2Field],
                            originalArgument: curPoint['original' + argumentField],
                            rotated: rotated,
                            options: pointStyle,
                            tag: curPoint[tagField],
                            series: self
                        });
                        self.pointsByArgument[point.argument.valueOf()] = self.pointsByArgument[point.argument.valueOf()] || point;
                        self.points.push(point)
                    }
                }
                self.originalPoints = self.points;
                self._segmentPoints()
            },
            _preparePointStyle: function(options) {
                var self = this,
                    type = self.type,
                    defaultPointOptions = self.userOptions.point,
                    defaultPointStyle = self.styles.point,
                    isBar = ~type.indexOf('bar'),
                    style,
                    mainColor = options.color && new DX.Color(options.color),
                    func;
                options.border = options.border || {};
                options.border.color = options.border.color || options.color;
                options.hoverStyle = options.hoverStyle || {};
                options.hoverStyle.color = options.hoverStyle.color || self.isIE8 && mainColor && mainColor.highlight(20) || isBar && options.color || undefined;
                options.hoverStyle.border = options.hoverStyle.border || {};
                options.hoverStyle.border.color = options.hoverStyle.border.color || options.color;
                options.selectionStyle = options.selectionStyle || {};
                options.selectionStyle.color = options.selectionStyle.color || self.isIE8 && mainColor && mainColor.highlight(20) || isBar && options.color || undefined;
                options.selectionStyle.border = options.selectionStyle.border || {};
                options.selectionStyle.border.color = options.selectionStyle.border.color || options.color;
                options = $.extend(true, {}, defaultPointOptions, options);
                style = self._parsePointStyleOptions(options, type);
                style.attributes.inh = false;
                style.label = $.extend(true, {}, self.styles.point.label);
                if (isBar) {
                    func = function(mode) {
                        if (!mode)
                            return false;
                        switch (mode.toLowerCase()) {
                            case"allseriespoints":
                            case"allargumentpoints":
                            case"none":
                                return true
                        }
                    };
                    style.attributes = $.extend(true, {}, defaultPointStyle.attributes, style.attributes);
                    style.states.normal = $.extend(true, {}, defaultPointStyle.states.normal, style.states.normal);
                    style.states.hover = $.extend(true, {}, defaultPointStyle.states.hover, style.states.hover);
                    style.states.selected = $.extend(true, {}, defaultPointStyle.states.selected, style.states.selected);
                    style.attributes.r = style.states.normal.r = style.states.hover.r = style.states.selected.r = defaultPointStyle.attributes.r;
                    style.hoverMode = func(self.options.hoverMode) && self.options.hoverMode;
                    style.selectionMode = func(self.options.selectionMode) && self.options.selectionMode;
                    style.visible = true
                }
                return style
            },
            _getPointStyle: function(seriesPointStyle, index, argument, value1, value2, tag) {
                var self = this,
                    customizePointObject,
                    currentPointOptions,
                    currentPointStyle,
                    customizePoint = self.options.customizePoint;
                customizePointObject = {
                    index: index,
                    argument: argument,
                    seriesName: self.name,
                    tag: tag
                };
                if (value2) {
                    customizePointObject.rangeValue1 = value1;
                    customizePointObject.rangeValue2 = value2
                }
                else
                    customizePointObject.value = value1;
                currentPointOptions = customizePoint ? customizePoint.call(customizePointObject, customizePointObject) : {};
                if (!$.isEmptyObject(currentPointOptions)) {
                    currentPointStyle = self._preparePointStyle(currentPointOptions);
                    self.styles.pointStyles.push(currentPointStyle);
                    return currentPointStyle
                }
                else
                    return seriesPointStyle
            },
            _segmentPoints: function() {
                var _this = this,
                    segment = [];
                _this.segments = [];
                $.each(_this.points, function(_, point) {
                    if (point.hasValue())
                        segment.push(point);
                    else if (segment.length !== 0) {
                        _this.segments.push(segment);
                        segment = []
                    }
                });
                if (segment.length)
                    _this.segments.push(segment)
            },
            _parseOptions: function(options) {
                this.options = {
                    incidentOccured: options.incidentOccured,
                    rotated: !!options.rotated,
                    seriesGroup: options.seriesGroup,
                    seriesLabelsGroup: options.seriesLabelsGroup,
                    seriesTrackerGroup: options.seriesTrackerGroup,
                    markerTrackerGroup: options.markerTrackerGroup,
                    argumentCategories: options.argumentCategories,
                    argumentAxisType: options.argumentAxisType,
                    argumentType: options.argumentType,
                    argumentField: options.specificType === 'candlestick' || options.specificType === 'stock' ? options.argumentField || 'date' : options.argumentField || 'arg',
                    valueCategories: options.valueCategories,
                    valueAxisType: options.valueAxisType,
                    valueType: options.valueType,
                    valueField: options.valueField || 'val',
                    rangeValue1Field: options.rangeValue1Field || 'val1',
                    rangeValue2Field: options.rangeValue2Field || 'val2',
                    tagField: options.tagField || 'tag',
                    sizeField: options.sizeField || 'size',
                    openValueField: options.openValueField || 'open',
                    closeValueField: options.closeValueField || 'close',
                    highValueField: options.highValueField || 'high',
                    lowValueField: options.lowValueField || 'low',
                    selectionMode: (options.selectionMode || '').toLowerCase(),
                    hoverMode: (options.hoverMode || '').toLowerCase(),
                    showInLegend: options.showInLegend !== undefined ? options.showInLegend : true,
                    customizePoint: $.isFunction(options.customizePoint) ? options.customizePoint : undefined
                };
                if (!$.isFunction(this.options.incidentOccured))
                    this.options.incidentOccured = $.noop;
                this.name = options.name;
                this.axis = options.axis;
                this.pane = options.pane;
                this.styles = this.parseStyleOptions(options);
                if (this.adjustOptions)
                    this.adjustOptions()
            },
            _createPointState: function(options, needInh, needHatching) {
                var border = options.border,
                    state = {
                        strokeWidth: border.visible ? border.width || 0 : 0,
                        stroke: border.visible && border.width ? border.color : 'none',
                        fill: options.color,
                        r: options.size + (border.visible && options.size !== 0 ? ~~(border.width / 2) || 0 : 0)
                    };
                if (needInh)
                    state.inh = true;
                if (needHatching) {
                    state.hatching = {};
                    state.hatching = {
                        direction: options.hatching && options.hatching.direction,
                        width: options.hatching && options.hatching.width,
                        step: options.hatching && options.hatching.step,
                        opacity: options.hatching && options.hatching.opacity
                    }
                }
                return state
            },
            _createSeriesState: function(options, needRadius, needHatching, dashStyle) {
                var border = options.border,
                    state = {
                        strokeWidth: border.visible ? border.width || 0 : 0,
                        stroke: border.visible && border.width ? border.color : 'none',
                        fill: options.color,
                        dashStyle: options.dashStyle || dashStyle,
                        lineWidth: options.width,
                        opacity: options.opacity
                    };
                if (needRadius)
                    state.r = options.cornerRadius;
                if (needHatching) {
                    state.hatching = {};
                    state.hatching = {
                        direction: options.hatching.direction,
                        width: options.hatching.width,
                        step: options.hatching.step,
                        opacity: options.hatching.opacity
                    }
                }
                return state
            },
            _parsePointStyleOptions: function(options, type) {
                var isBar = type && ~type.indexOf('bar'),
                    pointNormalState = this._createPointState(options, true),
                    pointHoverState = this._createPointState(options.hoverStyle, false, isBar),
                    pointSelectedState = this._createPointState(options.selectionStyle, false, isBar),
                    pointAttr = {},
                    pointAttributes;
                $.each(['align', 'translateX', 'translateY', 'rotate', 'linejoin', 'linecap', 'style'], function(i, val) {
                    if (val in options)
                        pointAttr[val] = options[val]
                });
                pointAttributes = $.extend(true, {}, pointNormalState, pointAttr);
                return {
                        visible: options.visible,
                        symbol: options.symbol,
                        image: options.image,
                        attributes: pointAttributes,
                        seriesName: options.seriesName,
                        selectionMode: (options.selectionMode || '').toLowerCase(),
                        hoverMode: (options.hoverMode || '').toLowerCase(),
                        states: {
                            normal: pointNormalState,
                            hover: pointHoverState,
                            selected: pointSelectedState
                        }
                    }
            },
            _parseLabelStyleOptions: function(options) {
                var labelOptions = options.label,
                    labelFont = labelOptions.font,
                    labelBorder = labelOptions.border,
                    labelConnector = labelOptions.connector,
                    labelAttributes = {
                        align: labelOptions.alignment,
                        font: {
                            color: labelOptions.backgroundColor === 'none' && labelFont.color.toLowerCase() === '#ffffff' && labelOptions.position !== 'inside' ? options.color : labelFont.color,
                            family: labelFont.family,
                            weight: labelFont.weight,
                            size: labelFont.size,
                            opacity: labelFont.opacity
                        },
                        style: labelOptions.style
                    },
                    backgroundAttr = {
                        fill: labelOptions.backgroundColor || options.color,
                        strokeWidth: labelBorder.visible ? labelBorder.width || 0 : 0,
                        stroke: labelBorder.visible && labelBorder.width ? labelBorder.color : 'none',
                        dashStyle: labelBorder.dashStyle
                    },
                    connectorAttr = {
                        stroke: labelConnector.visible && labelConnector.width ? labelConnector.color || options.color : 'none',
                        strokeWidth: labelConnector.visible ? labelConnector.width || 0 : 0
                    };
                return {
                        format: labelOptions.format,
                        argumentFormat: labelOptions.argumentFormat,
                        precision: labelOptions.precision,
                        argumentPrecision: labelOptions.argumentPrecision,
                        percentPrecision: labelOptions.percentPrecision,
                        customizeText: $.isFunction(labelOptions.customizeText) ? labelOptions.customizeText : undefined,
                        attributes: labelAttributes,
                        visible: labelFont.size !== 0 ? labelOptions.visible : false,
                        showForZeroValues: labelOptions.showForZeroValues,
                        horizontalOffset: labelOptions.horizontalOffset,
                        verticalOffset: labelOptions.verticalOffset,
                        radialOffset: labelOptions.radialOffset,
                        background: backgroundAttr,
                        position: labelOptions.position,
                        connector: connectorAttr,
                        rotationAngle: labelOptions.rotationAngle
                    }
            },
            parseStyleOptions: function(options) {
                var self = this,
                    combinedOptions = $.extend(true, {}, this.getDefaultStyleOptions(), options),
                    normalState = self._createSeriesState(combinedOptions, true),
                    hoverState = self._createSeriesState(combinedOptions.hoverStyle, false, true, combinedOptions.dashStyle),
                    selectedState = self._createSeriesState(combinedOptions.selectionStyle, false, true, combinedOptions.dashStyle),
                    attr = {},
                    attributes,
                    commonPointStyle;
                $.each(['align', 'translateX', 'translateY', 'rotate', 'linejoin', 'linecap', 'opacity', 'style'], function(i, val) {
                    if (combinedOptions[val])
                        attr[val] = combinedOptions[val]
                });
                attributes = $.extend(true, {}, normalState, attr);
                commonPointStyle = self._parsePointStyleOptions(combinedOptions.point);
                commonPointStyle.label = self._parseLabelStyleOptions(combinedOptions);
                return {
                        themeColor: combinedOptions.color,
                        attributes: attributes,
                        maxLabelCount: combinedOptions.maxLabelCount,
                        minSegmentSize: combinedOptions.minSegmentSize,
                        minBarSize: combinedOptions.minBarSize,
                        reduction: {
                            color: combinedOptions.reduction.color,
                            level: combinedOptions.reduction.level,
                            innerColor: combinedOptions.innerColor
                        },
                        states: {
                            normal: normalState,
                            hover: hoverState,
                            selected: selectedState
                        },
                        point: commonPointStyle
                    }
            },
            canRenderCompleteHandle: function() {
                var result = this._canRenderCompleteHandle;
                delete this._canRenderCompleteHandle;
                return !!result
            },
            _isTypeSupported: function(data) {
                return utils.isString(data) || utils.isNumber(data) || utils.isDate(data)
            },
            _getPointSize: function() {
                if (this.styles.point.visible)
                    return this.styles.point.attributes.r * 2;
                else
                    return 2
            },
            getDefaultStyleOptions: function() {
                return {
                        color: '#000000',
                        border: {
                            visible: false,
                            width: 1,
                            color: '#000000'
                        },
                        width: 2,
                        dashStyle: 'solid',
                        cornerRadius: 0,
                        innerColor: '#ffffff',
                        reduction: {color: '#FF0000'},
                        maxLabelCount: undefined,
                        minSegmentSize: undefined,
                        minBarSize: undefined,
                        point: {
                            visible: true,
                            symbol: 'circle',
                            color: '#000000',
                            size: 6,
                            seriesName: this.name,
                            border: {
                                visible: false,
                                width: 1,
                                color: '#000000'
                            },
                            hoverStyle: {
                                color: '#000000',
                                border: {
                                    visible: true,
                                    width: 2,
                                    color: '#ffffff'
                                },
                                size: 6
                            },
                            selectionStyle: {
                                color: '#000000',
                                border: {
                                    visible: true,
                                    width: 2,
                                    color: '#ffffff'
                                },
                                size: 6
                            }
                        },
                        label: {
                            visible: false,
                            showForZeroValues: true,
                            alignment: 'center',
                            font: {
                                family: "'SegoeUI', 'Segoe UI', 'HelveticaNeue', 'Helvetica Neue', 'Trebuchet MS', Verdana",
                                weight: 400,
                                color: '#ffffff',
                                size: 14
                            },
                            rotationAngle: 0,
                            horizontalOffset: 0,
                            verticalOffset: 0,
                            radialOffset: 0,
                            format: '',
                            argumentFormat: '',
                            precision: 0,
                            argumentPrecision: 0,
                            position: 'outside',
                            connector: {
                                visible: false,
                                width: 1
                            },
                            border: {
                                visible: false,
                                width: 1,
                                color: '#808080',
                                dashStyle: 'solid'
                            }
                        },
                        hoverStyle: {
                            hatching: {
                                direction: 'none',
                                width: 2,
                                step: 6,
                                opacity: 0.75
                            },
                            color: '#000000',
                            border: {
                                visible: false,
                                width: 1,
                                color: '#000000'
                            },
                            width: 3
                        },
                        selectionStyle: {
                            hatching: {
                                direction: 'right',
                                width: 2,
                                step: 6,
                                opacity: 0.5
                            },
                            color: '#000000',
                            border: {
                                visible: false,
                                width: 1,
                                color: '#000000'
                            },
                            width: 3
                        }
                    }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file lineSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            animationConst = series.consts.animations;
        series.LineSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options, isRangeSeries) {
                options.specificType = options.specificType || 'line';
                this.callBase(renderer, options, isRangeSeries);
                this.paths = this.paths || []
            },
            dispose: function() {
                this.paths = null;
                this.callBase()
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled) {
                var self = this;
                if (!self.segments)
                    return;
                self.paths = [];
                if (animationEnabled) {
                    labelsGroup.applySettings(animationConst.hideGroup);
                    seriesMarkersGroup.applySettings(animationConst.hideGroup)
                }
                $.each(self.segments, function(i, segment) {
                    if (self.styles.attributes.strokeWidth > 0)
                        self.drawLine(seriesElementsGroup, animationEnabled ? self.getZeroPathPoints(i) : segment);
                    self.drawPoints(seriesMarkersGroup, labelsGroup, segment)
                });
                animationEnabled && self.animate(function() {
                    seriesMarkersGroup.animate(animationConst.showGroup, animationConst.showDuration);
                    labelsGroup.animate(animationConst.showGroup, animationConst.showDuration)
                })
            },
            _drawTrackersForSegment: function(index, segment) {
                this.drawLineTracker(segment);
                this.callBase(index, segment)
            },
            applyNormalStyle: function(mode) {
                var self = this;
                if (self.paths) {
                    self.applyPathNormalStyle();
                    self.applyPointNormalStyle(mode)
                }
            },
            applyHoverStyle: function(mode) {
                var self = this;
                if (self.paths) {
                    self.applyPathHoverStyle();
                    self.applyPointHoverStyle(mode)
                }
            },
            applySelectionStyle: function(mode) {
                var self = this;
                if (self.paths) {
                    self.applyPathSelectionStyle();
                    self.applyPointSelectionStyle(mode)
                }
            },
            animate: function(complete) {
                this.animatePaths(complete)
            }
        }).include(series.SeriesPointsDrawerMixin).include(series.LineDrawerMixin).include(series.LineSeriesAdjustOptionsMixin).include(series.pointVisualizationMixin).include(series.pathVisualizationMixin).include(series.pointsAnimation).include(series.pathAnimation).include(series.SeriesDataFilterMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file areaSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            animationConst = series.consts.animations;
        series.AreaSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options, isRangeSeries) {
                this.type = options.specificType = options.specificType || 'area';
                this.callBase(renderer, options, isRangeSeries);
                this.areaSegments = this.areaSegments || []
            },
            dispose: function() {
                var _this = this;
                _this.areas = null;
                _this.areaSegments = null;
                _this.paths = null;
                _this.callBase()
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled) {
                var self = this,
                    lineSegment,
                    areaSegment;
                self.paths = [];
                self.areas = [];
                if (!self.segments)
                    return;
                if (animationEnabled) {
                    labelsGroup.applySettings(animationConst.hideGroup);
                    seriesMarkersGroup.applySettings(animationConst.hideGroup)
                }
                $.each(self.segments, function(index, segment) {
                    self.prepareSegments(index);
                    if (animationEnabled) {
                        areaSegment = self.getZeroAreaPoints(index);
                        lineSegment = self.getZeroPathPoints(index)
                    }
                    else {
                        areaSegment = self.areaSegments[index];
                        lineSegment = segment
                    }
                    self.drawPoints(seriesMarkersGroup, labelsGroup, segment);
                    self.drawArea(seriesElementsGroup, index, areaSegment);
                    if (self.styles.attributes.strokeWidth > 0 || self.styles.states.hover.strokeWidth > 0 || self.styles.states.selected.strokeWidth > 0)
                        self.drawLine(seriesElementsGroup, lineSegment)
                });
                animationEnabled && self.animate(function() {
                    seriesMarkersGroup.animate(animationConst.showGroup, animationConst.showDuration);
                    labelsGroup.animate(animationConst.showGroup, animationConst.showDuration)
                })
            },
            _drawTrackersForSegment: function(index, segment) {
                this.drawAreaTracker(index, segment);
                this.callBase(index, segment)
            },
            applyNormalStyle: function(mode) {
                this.applyPointNormalStyle(mode);
                this.applyPathNormalStyle();
                this.applyAreaNormalStyle()
            },
            applyHoverStyle: function(mode) {
                this.applyPointHoverStyle(mode);
                this.applyPathHoverStyle();
                this.applyAreaHoverStyle()
            },
            applySelectionStyle: function(mode) {
                this.applyPointSelectionStyle(mode);
                this.applyPathSelectionStyle();
                this.applyAreaSelectionStyle()
            },
            animate: function(complete) {
                this.animateAreas(complete);
                this.animatePaths()
            }
        }).include(series.AreaDrawerMixin).include(series.SeriesPointsDrawerMixin).include(series.LineDrawerMixin).include(series.AreaSeriesAdjustOptionsMixin).include(series.pointVisualizationMixin).include(series.pathVisualizationMixin).include(series.areaVisualizationMixin).include(series.pointsAnimation).include(series.pathAnimation).include(series.areaAnimation).include(series.specialAreaMethodsMixin).include(series.SeriesDataFilterMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file barSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            animationConst = series.consts.animations;
        series.BarSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options, isRangeSeries) {
                options.specificType = options.specificType || 'bar';
                this.callBase(renderer, options, isRangeSeries);
                this.stackName = options.stack || 'default'
            },
            _applyClippings: function(seriesElementsOptions, seriesMarkersOptions, labelsGroupOptions) {
                if (this.paneClipRectID) {
                    seriesElementsOptions.clipId = this.paneClipRectID;
                    labelsGroupOptions.clipId = this.paneClipRectID
                }
            },
            _applyTrackersClippings: function() {
                if (this.paneClipRectID)
                    this.options.markerTrackerGroup.applySettings({clipId: this.paneClipRectID})
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled) {
                var self = this;
                if (self.points.length && self.hoverPattern) {
                    self.styles.point.states.hover.fill = self.hoverPattern.id;
                    self.styles.point.states.selected.fill = self.selectedPattern.id
                }
                $.each(self.styles.pointStyles, function(_, style) {
                    if (style)
                        if (style.hoverPattern) {
                            style.states.hover.fill = style.hoverPattern.id;
                            style.states.selected.fill = style.selectedPattern.id
                        }
                });
                if (!self.segments)
                    return;
                if (animationEnabled) {
                    if (!this.options.rotated)
                        self.seriesGroup.applySettings({
                            scale: {
                                x: 1,
                                y: 0.001
                            },
                            translateY: this.translator.translateY('canvas_position_default')
                        });
                    else
                        self.seriesGroup.applySettings({
                            scale: {
                                x: 0.001,
                                y: 1
                            },
                            translateX: this.translator.translateX('canvas_position_default')
                        });
                    labelsGroup.applySettings(animationConst.hideGroup)
                }
                $.each(this.segments, function(i, segment) {
                    self.drawPoints(seriesMarkersGroup, labelsGroup, segment)
                });
                animationEnabled && self.animate(function() {
                    labelsGroup.animate(animationConst.showGroup, animationConst.showDuration)
                })
            },
            applyNormalStyle: function(mode) {
                this.applyPointNormalStyle(mode)
            },
            applyHoverStyle: function(mode) {
                this.applyPointHoverStyle(mode)
            },
            applySelectionStyle: function(mode) {
                this.applyPointSelectionStyle(mode)
            },
            animate: function(complete) {
                var _this = this,
                    group = this.seriesGroup;
                group.animate({
                    scale: {
                        x: 1,
                        y: 1
                    },
                    translate: {
                        y: 0,
                        x: 0
                    }
                }, {}, complete)
            }
        }).include(series.SeriesPointsDrawerMixin).include(series.BarSeriesAdjustOptionsMixin).include(series.pointVisualizationMixin).include(series.pointsAnimation).redefine(series.specialBarMethodsMixin).redefine(series.SeriesDataFilterMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file candleStickSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            isDefined = DX.utils.isDefined;
        series.CandleStickSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options) {
                options.specificType = options.specificType || 'candlestick';
                this.callBase(renderer, options)
            },
            dispose: function() {
                var _this = this;
                _this.hoverPatternReduction = null;
                _this.selectedPatternReduction = null;
                _this.callBase()
            },
            _applyClippings: function(seriesElementsOptions, seriesMarkersOptions, labelsGroupOptions) {
                if (this.paneClipRectID) {
                    seriesElementsOptions.clipId = this.paneClipRectID;
                    labelsGroupOptions.clipId = this.paneClipRectID;
                    seriesMarkersOptions.clipId = this.paneClipRectID
                }
            },
            _applyTrackersClippings: function() {
                if (this.paneClipRectID)
                    this.options.markerTrackerGroup.applySettings({clipId: this.paneClipRectID})
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup) {
                var self = this,
                    markerGroups = self.createMarkerGroups(seriesMarkersGroup);
                $.each(self.points, function(i, point) {
                    switch (point.pointClassName) {
                        case'dx-candle-reduction':
                            point.options.states.hover.fill = self.hoverPatternReduction.id;
                            point.options.states.selected.fill = self.selectedPatternReduction.id;
                            point.options.states.hover.stroke = self.hoverPatternReduction.id;
                            point.options.states.selected.stroke = self.selectedPatternReduction.id;
                            break;
                        case'dx-candle-default':
                            point.options.states.hover.fill = self.hoverPattern.id;
                            point.options.states.selected.fill = self.selectedPattern.id;
                            point.options.states.hover.stroke = self.hoverPattern.id;
                            point.options.states.selected.stroke = self.selectedPattern.id;
                            break;
                        case'dx-candle-reduction dx-candle-positive':
                            point.options.states.hover.stroke = self.hoverPatternReduction.id;
                            point.options.states.selected.stroke = self.selectedPatternReduction.id;
                            break;
                        default:
                            point.options.states.hover.stroke = self.hoverPattern.id;
                            point.options.states.selected.stroke = self.selectedPattern.id;
                            break
                    }
                });
                self.drawPoints(markerGroups, labelsGroup, self.points);
                return this
            },
            applyNormalStyle: function(mode) {
                this.applyPointNormalStyle(mode)
            },
            applyHoverStyle: function(mode) {
                this.applyPointHoverStyle(mode)
            },
            applySelectionStyle: function(mode) {
                this.applyPointSelectionStyle(mode)
            },
            animate: function() {
                this.animatePoints()
            }
        }).include(series.SeriesPointsDrawerMixin).include(series.CandleStickSeriesAdjustOptionsMixin).include(series.pointVisualizationMixin).include(series.pointsAnimation).redefine(series.specialCandleStickMethodsMixin).include(series.FinancialSeriesDataResamplerMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file stockSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series;
        series.StockSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options) {
                options.specificType = options.specificType || 'stock';
                this.callBase(renderer, options)
            },
            _applyClippings: function(seriesElementsOptions, seriesMarkersOptions, labelsGroupOptions) {
                if (this.paneClipRectID) {
                    seriesElementsOptions.clipId = this.paneClipRectID;
                    labelsGroupOptions.clipId = this.paneClipRectID;
                    seriesMarkersOptions.clipId = this.paneClipRectID
                }
            },
            _applyTrackersClippings: function() {
                if (this.paneClipRectID)
                    this.options.markerTrackerGroup.applySettings({clipId: this.paneClipRectID})
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup) {
                var self = this,
                    hoverStroke = self.styles.states.hover.stroke,
                    selectedStroke = self.styles.states.selected.stroke,
                    normalStroke = self.styles.states.normal.stroke,
                    reductionColor = self.styles.reduction.color,
                    markerGroups = self.createMarkerGroups(seriesMarkersGroup);
                $.each(self.points, function(i, point) {
                    switch (point.pointClassName) {
                        case'dx-candle-reduction':
                        case'dx-candle-reduction dx-candle-positive':
                            point.options.states.hover.stroke = normalStroke === hoverStroke ? reductionColor : hoverStroke;
                            point.options.states.selected.stroke = normalStroke === selectedStroke ? reductionColor : selectedStroke;
                            break;
                        default:
                            point.options.states.hover.stroke = hoverStroke;
                            point.options.states.selected.stroke = selectedStroke;
                            break
                    }
                });
                self.drawPoints(markerGroups, labelsGroup, self.points);
                return this
            },
            applyNormalStyle: function(mode) {
                this.applyPointNormalStyle(mode)
            },
            applyHoverStyle: function(mode) {
                this.applyPointHoverStyle(mode)
            },
            applySelectionStyle: function(mode) {
                this.applyPointSelectionStyle(mode)
            },
            animate: function() {
                this.animatePoints()
            }
        }).include(series.SeriesPointsDrawerMixin).include(series.CandleStickSeriesAdjustOptionsMixin).include(series.pointVisualizationMixin).include(series.pointsAnimation).redefine(series.specialCandleStickMethodsMixin).include(series.FinancialSeriesDataResamplerMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file splineSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            animationConst = series.consts.animations;
        series.SplineSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options, isRangeSeries) {
                options.specificType = options.specificType || 'spline';
                this.callBase(renderer, options, isRangeSeries)
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled) {
                var self = this;
                self.paths = [];
                if (!self.segments)
                    return;
                if (animationEnabled) {
                    labelsGroup.applySettings(animationConst.hideGroup);
                    seriesMarkersGroup.applySettings(animationConst.hideGroup)
                }
                $.each(self.segments, function(index, segment) {
                    self.prepareSegments(index);
                    var s = animationEnabled ? self.getZeroPathPoints(index) : self.preparedSegments[index];
                    if (self.styles.attributes.strokeWidth > 0)
                        self.drawSpline(seriesElementsGroup, index, s);
                    self.drawPoints(seriesMarkersGroup, labelsGroup, segment)
                });
                animationEnabled && self.animate(function() {
                    seriesMarkersGroup.animate(animationConst.showGroup, animationConst.showDuration);
                    labelsGroup.animate(animationConst.showGroup, animationConst.showDuration)
                })
            },
            _drawTrackersForSegment: function(index, segment) {
                this.drawSplineTracker(index);
                this.callBase(index, segment)
            },
            applyNormalStyle: function(mode) {
                var self = this;
                if (self.paths) {
                    self.applyPathNormalStyle();
                    self.applyPointNormalStyle(mode)
                }
            },
            applyHoverStyle: function(mode) {
                var self = this;
                if (self.paths) {
                    self.applyPathHoverStyle();
                    self.applyPointHoverStyle(mode)
                }
            },
            applySelectionStyle: function(mode) {
                var self = this;
                if (self.paths) {
                    self.applyPathSelectionStyle();
                    self.applyPointSelectionStyle(mode)
                }
            },
            animate: function(complete) {
                this.animatePaths(complete)
            }
        }).include(series.SplineDrawerMixin).include(series.SeriesPointsDrawerMixin).include(series.LineSeriesAdjustOptionsMixin).include(series.pointVisualizationMixin).include(series.pathVisualizationMixin).include(series.pointsAnimation).include(series.pathAnimation).include(series.SeriesDataFilterMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file splineAreaSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            animationConst = series.consts.animations;
        series.SplineAreaSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options, isRangeSeries) {
                options.specificType = options.specificType || 'splinearea';
                this.callBase(renderer, options, isRangeSeries);
                this.areas = this.areas || [];
                this.areaSegments = this.areaSegments || []
            },
            dispose: function() {
                var _this = this;
                _this.areas = null;
                _this.areaSegments = null;
                _this.paths = null;
                _this.callBase()
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled) {
                var self = this,
                    pathSegment,
                    areaSegment;
                self.paths = [];
                self.areas = [];
                if (!self.segments)
                    return;
                if (animationEnabled) {
                    labelsGroup.applySettings(animationConst.hideGroup);
                    seriesMarkersGroup.applySettings(animationConst.hideGroup)
                }
                $.each(self.segments, function(index, segment) {
                    self.prepareSegments(index);
                    if (animationEnabled) {
                        pathSegment = self.getZeroPathPoints(index);
                        areaSegment = self.getZeroAreaPoints(index)
                    }
                    else {
                        pathSegment = self.preparedSegments[index];
                        areaSegment = self.areaSegments[index]
                    }
                    self.drawPoints(seriesMarkersGroup, labelsGroup, segment);
                    self.drawSplineArea(seriesElementsGroup, index, areaSegment);
                    if (self.styles.attributes.strokeWidth > 0 || self.styles.states.hover.strokeWidth > 0 || self.styles.states.selected.strokeWidth > 0)
                        self.drawSpline(seriesElementsGroup, index, pathSegment)
                });
                if (self.hoverPattern) {
                    self.styles.area.states.hover.fill = self.hoverPattern.id;
                    self.styles.area.states.selected.fill = self.selectedPattern.id;
                    self.styles.states.hover.fill = 'none';
                    self.styles.states.selected.fill = 'none'
                }
                animationEnabled && self.animate(function() {
                    seriesMarkersGroup.animate(animationConst.showGroup, animationConst.showDuration);
                    labelsGroup.animate(animationConst.showGroup, animationConst.showDuration)
                })
            },
            _drawTrackersForSegment: function(index, segment) {
                this.drawSplineAreaTracker(index, segment);
                this.callBase(index, segment)
            },
            applyNormalStyle: function(mode) {
                this.applyPointNormalStyle(mode);
                this.applyPathNormalStyle();
                this.applyAreaNormalStyle()
            },
            applyHoverStyle: function(mode) {
                this.applyPointHoverStyle(mode);
                this.applyPathHoverStyle();
                this.applyAreaHoverStyle()
            },
            applySelectionStyle: function(mode) {
                this.applyPointSelectionStyle(mode);
                this.applyPathSelectionStyle();
                this.applyAreaSelectionStyle()
            },
            animate: function(complete) {
                this.animateAreas(complete);
                this.animatePaths()
            }
        }).include(series.SplineDrawerMixin).include(series.SeriesPointsDrawerMixin).redefine(series.SplineAreaDrawerMixin).include(series.AreaSeriesAdjustOptionsMixin).include(series.pointVisualizationMixin).include(series.pathVisualizationMixin).include(series.areaVisualizationMixin).include(series.pointsAnimation).include(series.pathAnimation).include(series.splineAreaAnimation).include(series.specialAreaMethodsMixin).include(series.SeriesDataFilterMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file scatterSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            animationConst = series.consts.animations;
        series.ScatterSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options) {
                options.specificType = options.specificType || 'scatter';
                this.callBase(renderer, options)
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled) {
                var self = this;
                if (!self.segments)
                    return;
                if (animationEnabled)
                    labelsGroup.applySettings(animationConst.hideGroup);
                $.each(this.segments, function(i, segment) {
                    self.drawPoints(seriesMarkersGroup, labelsGroup, segment, animationEnabled)
                });
                animationEnabled && self.animate(function() {
                    labelsGroup.animate(animationConst.showGroup, animationConst.showDuration)
                })
            },
            applyNormalStyle: function(mode) {
                this.applyPointNormalStyle(mode)
            },
            applyHoverStyle: function(mode) {
                this.applyPointHoverStyle(mode)
            },
            applySelectionStyle: function(mode) {
                this.applyPointSelectionStyle(mode)
            },
            animate: function(complete) {
                this.animatePoints(complete)
            }
        }).include(series.SeriesPointsDrawerMixin).include(series.pointVisualizationMixin).include(series.pointsAnimation).include(series.SeriesDataFilterMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangeAreaSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            animationConst = series.consts.animations;
        series.RangeAreaSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options) {
                options.specificType = options.specificType || 'rangearea';
                this.callBase(renderer, options, true);
                this.areaSegments = this.areaSegments || []
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled) {
                var self = this;
                self.areas = [];
                if (!self.segments)
                    return;
                if (animationEnabled) {
                    labelsGroup.applySettings(animationConst.hideGroup);
                    seriesMarkersGroup.applySettings(animationConst.hideGroup)
                }
                $.each(self.segments, function(index, segment) {
                    self.prepareSegments(index);
                    self.drawPoints(seriesMarkersGroup, labelsGroup, segment);
                    self.drawArea(seriesElementsGroup, index, animationEnabled ? self.getZeroAreaPoints(index) : self.areaSegments[index])
                });
                animationEnabled && self.animate(function() {
                    seriesMarkersGroup.animate(animationConst.showGroup, animationConst.showDuration);
                    labelsGroup.animate(animationConst.showGroup, animationConst.showDuration)
                })
            },
            _drawTrackersForSegment: function(index, segment) {
                this.drawAreaTracker(index, segment);
                this.callBase(index, segment)
            },
            applyNormalStyle: function(mode) {
                this.applyPointNormalStyle(mode);
                this.applyAreaNormalStyle()
            },
            applyHoverStyle: function(mode) {
                this.applyPointHoverStyle(mode);
                this.applyAreaHoverStyle()
            },
            applySelectionStyle: function(mode) {
                this.applyPointSelectionStyle(mode);
                this.applyAreaSelectionStyle()
            },
            animate: function(complete) {
                this.animateAreas(complete)
            }
        }).include(series.AreaDrawerMixin).include(series.SeriesPointsDrawerMixin).include(series.AreaSeriesAdjustOptionsMixin).include(series.pointVisualizationMixin).include(series.areaVisualizationMixin).include(series.pointsAnimation).include(series.areaAnimation).include(series.specialAreaMethodsMixin).include(series.RangeSeriesDataFilterMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file rangeBarSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            animationConst = series.consts.animations;
        series.RangeBarSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options) {
                options.specificType = options.specificType || 'rangebar';
                this.callBase(renderer, options, true)
            },
            _applyClippings: function(seriesElementsOptions, seriesMarkersOptions, labelsGroupOptions) {
                if (this.paneClipRectID) {
                    seriesElementsOptions.clipId = this.paneClipRectID;
                    labelsGroupOptions.clipId = this.paneClipRectID
                }
            },
            _applyTrackersClippings: function() {
                if (this.paneClipRectID)
                    this.options.markerTrackerGroup.applySettings({clipId: this.paneClipRectID})
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled) {
                var self = this;
                if (self.points.length && self.hoverPattern) {
                    self.styles.point.states.hover.fill = self.hoverPattern.id;
                    self.styles.point.states.selected.fill = self.selectedPattern.id
                }
                $.each(self.styles.pointStyles, function(_, style) {
                    if (style)
                        if (style.hoverPattern) {
                            style.states.hover.fill = style.hoverPattern.id;
                            style.states.selected.fill = style.selectedPattern.id
                        }
                });
                if (!self.segments)
                    return;
                if (animationEnabled) {
                    if (!this.options.rotated)
                        self.seriesGroup.applySettings({
                            scale: {
                                x: 1,
                                y: 0.001
                            },
                            translateY: this.translator.translateY('canvas_position_default')
                        });
                    else
                        self.seriesGroup.applySettings({
                            scale: {
                                x: 0.001,
                                y: 1
                            },
                            translateX: this.translator.translateX('canvas_position_default')
                        });
                    labelsGroup.applySettings(animationConst.hideGroup)
                }
                $.each(this.segments, function(i, segment) {
                    self.drawPoints(seriesMarkersGroup, labelsGroup, segment)
                });
                animationEnabled && self.animate(function() {
                    labelsGroup.animate(animationConst.showGroup, animationConst.showDuration)
                })
            },
            applyNormalStyle: function(mode) {
                this.applyPointNormalStyle(mode)
            },
            applyHoverStyle: function(mode) {
                this.applyPointHoverStyle(mode)
            },
            applySelectionStyle: function(mode) {
                this.applyPointSelectionStyle(mode)
            },
            animate: function(complete) {
                this.seriesGroup.animate({
                    scale: {
                        x: 1,
                        y: 1
                    },
                    translate: {
                        y: 0,
                        x: 0
                    }
                }, {}, complete)
            }
        }).include(series.SeriesPointsDrawerMixin).include(series.BarSeriesAdjustOptionsMixin).include(series.pointVisualizationMixin).include(series.pointsAnimation).include(series.RangeSeriesDataFilterMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file piePoint.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            statesConsts = series.consts.states,
            round = Math.round,
            getCosAndSin = DX.utils.getCosAndSin;
        series.PiePoint = series.BasePoint.inherit({
            ctor: function(data) {
                this.centerX = 300;
                this.centerY = 150;
                this.radiusOuter = 120;
                this.radiusInner = 0;
                this.INDENT_FROM_PIE = 30;
                this.CONNECTOR_LENGTH = 20;
                this.setLabelEllipsis = false;
                this.callBase(data);
                this.minValue = 0;
                this.tag = data.tag;
                this._pieTrackerAttrs = $.extend({}, this._trackerAttrs, {
                    inh: false,
                    fill: 'grey'
                })
            },
            translate: function(translator) {
                var self = this;
                self.translator = translator = translator || self.translator;
                if (!self.translator)
                    return;
                self.fromAngle = translator.translate(self.minValue);
                self.toAngle = translator.translate(self.value);
                self.middleAngle = translator.translate((self.value - self.minValue) / 2 + self.minValue)
            },
            correctValue: function(correction, percent) {
                var self = this;
                self.value += correction;
                self.minValue += correction;
                self.percent = percent;
                self.labelFormatObject.percent = percent
            },
            getTooltipCoords: function() {
                var angleFunctions = getCosAndSin(this.middleAngle);
                return {
                        x: this.centerX + (this.radiusInner + (this.radiusOuter - this.radiusInner) / 2) * angleFunctions.cos,
                        y: this.centerY - (this.radiusInner + (this.radiusOuter - this.radiusInner) / 2) * angleFunctions.sin,
                        offset: 0
                    }
            },
            correctPosition: function(correction) {
                var self = this;
                self.radiusInner = correction.radiusInner;
                self.radiusOuter = correction.radiusOuter;
                self.centerX = correction.centerX;
                self.centerY = correction.centerY
            },
            drawMarker: function(renderer, group, animationEnabled) {
                this.options.attributes.inh = false;
                var attr = animationEnabled ? $.extend({
                        scale: {
                            x: 0,
                            y: 0
                        },
                        translateX: this.centerX,
                        translateY: this.centerY
                    }, this.options.attributes) : this.options.attributes;
                this.graphic = renderer.createArc(this.centerX, this.centerY, this.radiusOuter, this.radiusInner, this.toAngle, this.fromAngle, attr).append(group);
                this._checkState()
            },
            drawTrackerMarker: function(renderer, trackerGroup) {
                this.trackerGraphic = renderer.createArc(this.centerX, this.centerY, this.radiusOuter, this.radiusInner, this.toAngle, this.fromAngle, this._pieTrackerAttrs).append(trackerGroup);
                this.trackerGraphic.data({point: this})
            },
            correctLabel: function() {
                this.correctLabelPosition();
                this.checkEllipsis();
                this.correctBackgroundPosition();
                this.rotateLabel();
                this.checkLabelPosition()
            },
            correctLabelPosition: function() {
                var bbox = this.label.getBBox(),
                    labelOptions = this.options.label,
                    angleFunctions = getCosAndSin(this.middleAngle),
                    align = 'center',
                    rad = this.radiusOuter + labelOptions.radialOffset,
                    x,
                    y;
                switch (labelOptions.position) {
                    case'outside':
                        rad += this.INDENT_FROM_PIE;
                        if (angleFunctions.cos > 0.1)
                            align = 'left';
                        else if (angleFunctions.cos < -0.1)
                            align = 'right';
                        x = this.centerX + rad * angleFunctions.cos;
                        break;
                    case'inside':
                        rad -= this.INDENT_FROM_PIE;
                        x = this.centerX + rad * angleFunctions.cos;
                        break;
                    case'columns':
                        rad += this.CONNECTOR_LENGTH;
                        if (angleFunctions.cos > 0) {
                            align = 'right';
                            x = this.series.canvas.width - this.series.canvas.right
                        }
                        else if (angleFunctions.cos < 0) {
                            align = 'left';
                            x = this.series.canvas.left
                        }
                        break
                }
                y = round(this.label.settings.y + this.centerY - rad * angleFunctions.sin - bbox.y - bbox.height / 2);
                this.label.applySettings({
                    x: x,
                    y: y,
                    align: align
                })
            },
            correctConnectorPosition: function() {
                if (this.options.label.position === 'inside')
                    return;
                if (!this.connector)
                    return;
                var angleFunctions = getCosAndSin(round(this.middleAngle)),
                    attributes = this.series.styles.attributes,
                    borderWidth = this.series.userOptions.containerBackgroundColor === attributes.stroke ? ~~(attributes.strokeWidth / 2) : ~~(-attributes.strokeWidth / 2),
                    rad = this.radiusOuter,
                    x1 = round(this.centerX + (rad - borderWidth) * angleFunctions.cos),
                    y1 = round(this.centerY - (rad - borderWidth) * angleFunctions.sin),
                    x2,
                    y2,
                    x3,
                    y3,
                    box,
                    labelOptions = this.options.label,
                    connector;
                x2 = round(this.centerX + (rad + labelOptions.radialOffset + this.CONNECTOR_LENGTH) * angleFunctions.cos);
                if (labelOptions.position === 'outside') {
                    y2 = round(this.centerY - (rad + labelOptions.radialOffset + this.CONNECTOR_LENGTH) * angleFunctions.sin);
                    this.connector.applySettings({points: [x1, y1, x2, y2]})
                }
                if (labelOptions.position === 'columns') {
                    box = this.insideLabelGroup.getBBox();
                    box.x = box.x + (this.insideLabelGroup.settings.translateX || 0);
                    box.y = box.y + (this.insideLabelGroup.settings.translateY || 0);
                    y2 = box.y + box.height / 2;
                    if (this.labelBackground)
                        x3 = box.x + box.width / 2;
                    else if (angleFunctions.cos < 0)
                        x3 = box.x + box.width;
                    else if (angleFunctions.cos > 0)
                        x3 = box.x;
                    y3 = y2;
                    this.connector.applySettings({points: [{
                                x: x1,
                                y: y1
                            }, {
                                x: x2,
                                y: y2
                            }, {
                                x: x3,
                                y: y3
                            }]})
                }
            },
            rotateLabel: function() {
                var labelOptions = this.options.label,
                    rad = this.radiusOuter + labelOptions.radialOffset,
                    angleFunctions = getCosAndSin(this.middleAngle),
                    x,
                    y,
                    box = this.insideLabelGroup.getBBox();
                switch (labelOptions.position) {
                    case'outside':
                        x = this.centerX + (rad + labelOptions.radialOffset + this.CONNECTOR_LENGTH) * angleFunctions.cos;
                        y = this.centerY - (rad + labelOptions.radialOffset + this.CONNECTOR_LENGTH) * angleFunctions.sin;
                        break;
                    case'inside':
                        x = box.x + box.width / 2;
                        y = box.y + box.height / 2;
                        break;
                    case'columns':
                        x = box.x + box.width / 2;
                        y = box.y + box.height / 2;
                        break
                }
                this.insideLabelGroup.applySettings({
                    x: x,
                    y: y,
                    rotate: labelOptions.rotationAngle
                })
            },
            checkEllipsis: function() {
                var self = this,
                    i,
                    LABEL_OFFSET = 10,
                    labelBox,
                    text,
                    textLength = 0,
                    linesLength = [],
                    numLastSpan = [],
                    maxLength,
                    numSpan,
                    index,
                    x,
                    y,
                    width,
                    rotationAngleFunction = getCosAndSin(self.options.label.rotationAngle),
                    canvas = self.series.canvas,
                    labelOptions = this.options.label,
                    angleFunctions = getCosAndSin(this.middleAngle),
                    borderX = this.centerX + (this.radiusOuter + this.CONNECTOR_LENGTH) * angleFunctions.cos;
                if (!self.label.tspans || !self.setLabelEllipsis)
                    return;
                labelBox = self.label.getBBox();
                x = labelBox.x + labelBox.width < self.centerX ? labelBox.x + labelBox.width : labelBox.x;
                y = labelBox.y + labelBox.height / 2;
                width = labelBox.x + labelBox.width < self.centerX ? -labelBox.width : labelBox.width;
                if (y + width * rotationAngleFunction.sin > canvas.height - canvas.bottom + LABEL_OFFSET || y + width * rotationAngleFunction.sin < canvas.top - LABEL_OFFSET || x + width * rotationAngleFunction.cos < canvas.left - LABEL_OFFSET || x + width * rotationAngleFunction.cos > canvas.width - canvas.right + LABEL_OFFSET || labelOptions.position === 'columns' && (angleFunctions.cos < 0 && borderX < x || angleFunctions.cos > 0 && borderX > x))
                    for (i = 0; i < self.label.tspans.length; i++) {
                        textLength += self.label.tspans[i].element.getNumberOfChars();
                        if (!self.label.tspans[i + 1] || self.label.tspans[i + 1].settings.dy > 0) {
                            linesLength.push(textLength);
                            numLastSpan.push(i);
                            textLength = 0
                        }
                    }
                while (y + width * rotationAngleFunction.sin > canvas.height - canvas.bottom + LABEL_OFFSET || y + width * rotationAngleFunction.sin < canvas.top - LABEL_OFFSET || x + width * rotationAngleFunction.cos < canvas.left - LABEL_OFFSET || x + width * rotationAngleFunction.cos > canvas.width - canvas.right + LABEL_OFFSET || labelOptions.position === 'columns' && (angleFunctions.cos < 0 && borderX < x || angleFunctions.cos > 0 && borderX > x)) {
                    maxLength = Math.max.apply(null, linesLength);
                    if (maxLength === 0)
                        break;
                    index = $.inArray(maxLength, linesLength);
                    numSpan = numLastSpan[index];
                    if (self.label.tspans[numSpan].element.textContent === "...") {
                        if (self.label.tspans[numSpan].settings.dy > 0 || !self.label.tspans[numSpan - 1])
                            linesLength[index] = 0;
                        else if (self.label.tspans[numSpan - 1]) {
                            self.label.tspans[numSpan].element.textContent = '';
                            numLastSpan[index] -= 1;
                            self.label.tspans[numSpan - 1].element.textContent += "..."
                        }
                    }
                    else {
                        text = self.label.tspans[numSpan].element.textContent;
                        text = text.substr(0, text.length - 1 - 3) + "...";
                        self.label.tspans[numSpan].element.textContent = text;
                        linesLength[index] -= 1
                    }
                    labelBox = self.label.getBBox();
                    x = labelBox.x + labelBox.width < self.centerX ? labelBox.x + labelBox.width : labelBox.x;
                    y = labelBox.y + labelBox.height / 2;
                    width = labelBox.x + labelBox.width < self.centerX ? -labelBox.width : labelBox.width
                }
            },
            checkLabelPosition: function() {
                var self = this,
                    groupBox = self.insideLabelGroup.getBBox(),
                    canvas = self.series.canvas;
                if (groupBox.y + groupBox.height > canvas.height - canvas.bottom)
                    self.insideLabelGroup.move(0, canvas.height - groupBox.y - groupBox.height - canvas.bottom);
                else if (groupBox.y < canvas.top)
                    self.insideLabelGroup.move(0, canvas.top - groupBox.y);
                if (groupBox.x + groupBox.width > canvas.width - canvas.right)
                    self.insideLabelGroup.move(canvas.width - canvas.right - groupBox.x - groupBox.width, 0);
                else if (groupBox.x < canvas.left)
                    self.insideLabelGroup.move(canvas.left - groupBox.x, 0)
            },
            isInVisibleArea: function() {
                return true
            },
            _populatePointShape: function(target, deltaRadius) {
                var self = this,
                    angleFunctions = DX.utils.getCosAndSin(this.middleAngle);
                target.x = this.centerX - ~~(deltaRadius * angleFunctions.cos);
                target.y = this.centerY + ~~(deltaRadius * angleFunctions.sin);
                target.outerRadius = this.radiusOuter + deltaRadius;
                target.innerRadius = this.radiusInner;
                target.startAngle = this.toAngle;
                target.endAngle = this.fromAngle
            },
            applyHoverStyle: function() {
                if (this.graphic) {
                    this._populatePointShape(this.options.states.hover, 0);
                    this.graphic.applySettings(this.options.states.hover);
                    this.graphic.toForeground();
                    this.graphic.addClass('dx-chart-hovered-point')
                }
                if (this.legend)
                    this.legend.applyHoverStyle(this);
                return this
            },
            applyNormalStyle: function() {
                if (this.graphic) {
                    this._populatePointShape(this.options.states.normal, 0);
                    this.graphic.applySettings(this.options.states.normal)
                }
                if (this.legend)
                    this.legend.applyNormalStyle(this);
                return this
            },
            applySelectionStyle: function() {
                if (this.graphic) {
                    this._populatePointShape(this.options.states.selected, 0);
                    this.graphic.applySettings(this.options.states.selected);
                    this.graphic.toForeground();
                    this.graphic.addClass('dx-chart-selected-point')
                }
                if (this.legend)
                    this.legend.applySelectionStyle(this);
                return this
            },
            animate: function(complete, duration, step) {
                this.graphic.animate({
                    scale: {
                        x: 1,
                        y: 1
                    },
                    translate: {
                        y: 0,
                        x: 0
                    }
                }, {
                    partitionDuration: duration,
                    step: step
                }, complete)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-core, file pieSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            HOVERING_SPACING = 20,
            LABEL_SPACING = 80,
            animationConst = series.consts.animations;
        series.PieSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options) {
                options.specificType = options.specificType || 'pie';
                this.callBase(renderer, options);
                this.labelSpace = this.styles.point.label.visible ? LABEL_SPACING : 0;
                this.hoverSpace = 0 && this.styles.point.states.enableHover ? HOVERING_SPACING : 0;
                this.innerRadius = this.type === 'pie' ? 0 : options.innerRadius;
                this.outerRadius = options.radius;
                this.redraw = false
            },
            createPatterns: function() {
                var renderer = this.renderer;
                $.each(this.points, function(i, point) {
                    if (!point.hoverPatternColor) {
                        point.hoverPatternColor = point.options.states.hover.fill;
                        point.selectedPatternColor = point.options.states.selected.fill
                    }
                    if (!point.hoverPattern) {
                        point.hoverPattern = renderer.createPattern(point.hoverPatternColor, point.options.states.hover.hatching);
                        point.selectedPattern = renderer.createPattern(point.selectedPatternColor, point.options.states.selected.hatching)
                    }
                    point.hoverPattern.append();
                    point.selectedPattern.append();
                    point.options.states.hover.fill = point.hoverPattern.id;
                    point.options.states.selected.fill = point.selectedPattern.id
                })
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled) {
                var labelSpace,
                    bbox,
                    paneSpaceHeight,
                    paneSpaceWidth,
                    min;
                this.drawPoints(seriesMarkersGroup, labelsGroup, this.points, animationEnabled);
                if (animationEnabled)
                    labelsGroup.applySettings(animationConst.hideGroup);
                if (this.styles.point.label.visible) {
                    labelSpace = 0;
                    if (this.styles.point.label.position === 'columns') {
                        $.each(this.points, function(i, point) {
                            point.setLabelEllipsis = true;
                            bbox = point.insideLabelGroup.getBBox();
                            labelSpace = Math.max(bbox.width + point.INDENT_FROM_PIE + point.options.label.radialOffset, labelSpace)
                        });
                        this.redraw = true;
                        paneSpaceHeight = this.canvas.height - this.canvas.top - this.canvas.bottom;
                        paneSpaceWidth = this.canvas.width - this.canvas.left - this.canvas.right;
                        min = paneSpaceWidth < paneSpaceHeight ? paneSpaceWidth : paneSpaceHeight;
                        if (labelSpace > min / 2 - labelSpace)
                            this.labelSpace = min / 2;
                        else
                            this.labelSpace = 2 * labelSpace
                    }
                    else
                        $.each(this.points, function(i, point) {
                            point.setLabelEllipsis = true;
                            point.correctLabel()
                        })
                }
                animationEnabled && this.animate(function() {
                    labelsGroup.animate(animationConst.showGroup, animationConst.showDuration)
                });
                return this
            },
            drawTrackers: function() {
                this.drawPointTrackers(this.points)
            },
            applyNormalStyle: function(mode) {
                this.applyPointNormalStyle(mode)
            },
            applyHoverStyle: function(mode) {
                this.applyPointHoverStyle(mode)
            },
            applySelectionStyle: function(mode) {
                this.applyPointSelectionStyle(mode)
            },
            animate: function(complete) {
                this.sequentialAnimatePoints(complete)
            }
        }).include(series.SeriesPointsDrawerMixin).include(series.BarSeriesAdjustOptionsMixin).include(series.pointVisualizationMixin).include(series.pointsAnimation).redefine(series.specialPieMethodsMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file stepLineSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            animationConst = series.consts.animations;
        series.StepLineSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options, isRangeSeries) {
                this.type = options.specificType = options.specificType || 'stepline';
                this.callBase(renderer, options, isRangeSeries)
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled) {
                var self = this;
                if (!self.segments)
                    return;
                self.paths = [];
                if (animationEnabled) {
                    labelsGroup.applySettings(animationConst.hideGroup);
                    seriesMarkersGroup.applySettings(animationConst.hideGroup)
                }
                $.each(self.segments, function(index, segment) {
                    self.prepareSegments(index);
                    var s = animationEnabled ? self.getZeroPathPoints(index) : self.preparedSegments[index];
                    self.drawStepLine(seriesElementsGroup, index, s);
                    self.drawPoints(seriesMarkersGroup, labelsGroup, segment)
                });
                animationEnabled && self.animate(function() {
                    seriesMarkersGroup.animate(animationConst.showGroup, animationConst.showDuration);
                    labelsGroup.animate(animationConst.showGroup, animationConst.showDuration)
                })
            },
            _drawTrackersForSegment: function(index, segment) {
                this.drawStepLineTracker(index, segment);
                this.callBase(index, segment)
            },
            applyNormalStyle: function(mode) {
                var self = this;
                if (self.paths) {
                    self.applyPathNormalStyle();
                    self.applyPointNormalStyle(mode)
                }
            },
            applyHoverStyle: function(mode) {
                var self = this;
                if (self.paths) {
                    self.applyPathHoverStyle();
                    self.applyPointHoverStyle(mode)
                }
            },
            applySelectionStyle: function(mode) {
                var self = this;
                if (self.paths) {
                    self.applyPathSelectionStyle();
                    self.applyPointSelectionStyle(mode)
                }
            },
            animate: function(complete) {
                this.animatePaths(complete)
            }
        }).include(series.SeriesPointsDrawerMixin).include(series.StepLineDrawerMixin).include(series.LineSeriesAdjustOptionsMixin).include(series.pointVisualizationMixin).include(series.pathVisualizationMixin).include(series.pointsAnimation).include(series.pathAnimation).include(series.SeriesDataFilterMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file stepAreaSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            animationConst = series.consts.animations;
        series.StepAreaSeries = series.BaseSeries.inherit({
            ctor: function(renderer, options, isRangeSeries) {
                this.type = options.specificType = options.specificType || 'steparea';
                this.areaSegments = this.areaSegments || [];
                this.callBase(renderer, options, isRangeSeries)
            },
            drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled) {
                var self = this,
                    areaSegment,
                    lineSegment;
                self.paths = [];
                self.areas = [];
                if (!self.segments)
                    return;
                if (animationEnabled) {
                    labelsGroup.applySettings(animationConst.hideGroup);
                    seriesMarkersGroup.applySettings(animationConst.hideGroup)
                }
                $.each(self.segments, function(index, segment) {
                    self.prepareSegments(index);
                    if (animationEnabled) {
                        areaSegment = self.getZeroAreaPoints(index);
                        lineSegment = self.getZeroPathPoints(index)
                    }
                    else {
                        lineSegment = self.preparedSegments[index];
                        areaSegment = self.areaSegments[index]
                    }
                    self.drawPoints(seriesMarkersGroup, labelsGroup, segment);
                    self.drawStepArea(seriesElementsGroup, index, areaSegment);
                    if (self.styles.attributes.strokeWidth > 0 || self.styles.states.hover.strokeWidth > 0 || self.styles.states.selected.strokeWidth > 0)
                        self.drawStepLine(seriesElementsGroup, index, lineSegment)
                });
                animationEnabled && self.animate(function() {
                    seriesMarkersGroup.animate(animationConst.showGroup, animationConst.showDuration);
                    labelsGroup.animate(animationConst.showGroup, animationConst.showDuration)
                })
            },
            _drawTrackersForSegment: function(index, segment) {
                this.drawStepAreaTrackers(index, segment);
                this.callBase(index, segment)
            },
            applyNormalStyle: function(mode) {
                this.applyPointNormalStyle(mode);
                this.applyPathNormalStyle();
                this.applyAreaNormalStyle()
            },
            applyHoverStyle: function(mode) {
                this.applyPointHoverStyle(mode);
                this.applyPathHoverStyle();
                this.applyAreaHoverStyle()
            },
            applySelectionStyle: function(mode) {
                this.applyPointSelectionStyle(mode);
                this.applyPathSelectionStyle();
                this.applyAreaSelectionStyle()
            },
            animate: function(complete) {
                this.animateAreas(complete);
                this.animatePaths()
            }
        }).include(series.SeriesPointsDrawerMixin).include(series.StepLineDrawerMixin).redefine(series.StepAreaDrawerMixin).include(series.AreaSeriesAdjustOptionsMixin).include(series.pointVisualizationMixin).include(series.pathVisualizationMixin).include(series.areaVisualizationMixin).include(series.pointsAnimation).include(series.pathAnimation).include(series.areaAnimation).include(series.specialAreaMethodsMixin).include(series.SeriesDataFilterMixin)
    })(jQuery, DevExpress);
    /*! Module viz-core, file bubbleSeries.js */
    (function($, DX) {
        var series = DX.viz.charts.series,
            isDefined = DX.utils.isDefined,
            utils = DX.utils,
            BaseSeries = series.BaseSeries,
            animationConst = series.consts.animations;
        var BubbleSeries = BaseSeries.inherit({
                ctor: function(renderer, options) {
                    options.specificType = options.specificType || 'bubble';
                    this.callBase(renderer, options)
                },
                _applyClippings: function(seriesElementsOptions, seriesMarkersOptions, labelsGroupOptions) {
                    if (this.paneClipRectID) {
                        seriesElementsOptions.clipId = this.paneClipRectID;
                        labelsGroupOptions.clipId = this.paneClipRectID;
                        seriesMarkersOptions.clipId = this.paneClipRectID
                    }
                },
                drawSeriesData: function(seriesElementsGroup, seriesMarkersGroup, labelsGroup, animationEnabled) {
                    if (this.points.length && this.hoverPattern) {
                        this.styles.point.states.hover.fill = this.hoverPattern.id;
                        this.styles.point.states.selected.fill = this.selectedPattern.id
                    }
                    if (animationEnabled)
                        labelsGroup.applySettings(animationConst.hideGroup);
                    this.drawPoints(seriesMarkersGroup, labelsGroup, this.points, animationEnabled);
                    animationEnabled && this.animate(function() {
                        labelsGroup.animate(animationConst.showGroup, animationConst.showDuration)
                    })
                },
                _applyTrackersClippings: function() {
                    if (this.paneClipRectID)
                        this.options.markerTrackerGroup.applySettings({clipId: this.paneClipRectID})
                },
                drawTrackers: function() {
                    this.trackerElements = [];
                    this.drawPointTrackers(this.points);
                    this._applyTrackersClippings()
                },
                applyNormalStyle: function(mode) {
                    this.applyPointNormalStyle(mode)
                },
                applyHoverStyle: function(mode) {
                    this.applyPointHoverStyle(mode)
                },
                applySelectionStyle: function(mode) {
                    this.applyPointSelectionStyle(mode)
                },
                animate: function(complete) {
                    this.animatePoints(complete)
                }
            }).include(series.SeriesPointsDrawerMixin).include(series.pointVisualizationMixin).redefine(series.specialBubbleMethodsMixin).include(series.BubleSeriesAdjustOptionsMixin).include(series.pointsAnimation).include(series.BubbleSeriesDataResamplerMixin);
        series.BubbleSeries = BubbleSeries
    })(jQuery, DevExpress);
    /*! Module viz-core, file seriesFamily.js */
    (function($, DX, undefined) {
        DX.viz.charts.series.SeriesFamily = DX.Class.inherit(function() {
            var ctor = function(options) {
                    var debug = DX.utils.debug;
                    debug.assert(options.type, 'type was not passed or empty');
                    var self = this,
                        stubFunction = $.noop;
                    $.extend(self, options);
                    self.type = self.type.toLowerCase();
                    self.series = [];
                    switch (self.type) {
                        case'bar':
                            self.adjustSeriesDimensions = adjustBarSeriesDimensions;
                            self.adjustSeriesValues = stubFunction;
                            self.updateSeriesValues = updateBarSeriesValues;
                            self.preparePointsForSharedTooltip = preparePointsForSharedTooltip;
                            break;
                        case'rangebar':
                            self.adjustSeriesDimensions = adjustBarSeriesDimensions;
                            self.adjustSeriesValues = stubFunction;
                            self.updateSeriesValues = stubFunction;
                            self.preparePointsForSharedTooltip = preparePointsForSharedTooltip;
                            break;
                        case'fullstackedbar':
                            self.fullStacked = true;
                            self.adjustSeriesDimensions = adjustStackedBarSeriesDimensions;
                            self.adjustSeriesValues = adjustStackedSeriesValues;
                            self.updateSeriesValues = updateStackedSeriesValues;
                            self.preparePointsForSharedTooltip = preparePointsForSharedTooltip;
                            break;
                        case'stackedbar':
                            self.adjustSeriesDimensions = adjustStackedBarSeriesDimensions;
                            self.adjustSeriesValues = adjustStackedSeriesValues;
                            self.updateSeriesValues = updateStackedSeriesValues;
                            self.preparePointsForSharedTooltip = preparePointsForSharedTooltip;
                            break;
                        case'fullstackedarea':
                        case'fullstackedline':
                            self.fullStacked = true;
                            self.adjustSeriesDimensions = stubFunction;
                            self.adjustSeriesValues = adjustStackedSeriesValues;
                            self.updateSeriesValues = stubFunction;
                            self.preparePointsForSharedTooltip = preparePointsForSharedTooltip;
                            break;
                        case'stackedarea':
                        case'stackedline':
                            self.adjustSeriesDimensions = stubFunction;
                            self.adjustSeriesValues = adjustStackedSeriesValues;
                            self.updateSeriesValues = stubFunction;
                            self.preparePointsForSharedTooltip = preparePointsForSharedTooltip;
                            break;
                        case'candlestick':
                        case'stock':
                            self.adjustSeriesDimensions = adjuistCandlestickSeriesDimensions;
                            self.adjustSeriesValues = stubFunction;
                            self.updateSeriesValues = stubFunction;
                            self.preparePointsForSharedTooltip = preparePointsForSharedTooltip;
                            break;
                        case'bubble':
                            self.adjustSeriesDimensions = adjustBubbleSeriesDimensions;
                            self.adjustSeriesValues = stubFunction;
                            self.updateSeriesValues = stubFunction;
                            self.preparePointsForSharedTooltip = preparePointsForSharedTooltip;
                            break;
                        default:
                            self.adjustSeriesDimensions = stubFunction;
                            self.adjustSeriesValues = stubFunction;
                            self.updateSeriesValues = stubFunction;
                            self.preparePointsForSharedTooltip = preparePointsForSharedTooltip;
                            break
                    }
                };
            var dispose = function() {
                    this.series = null;
                    this.translator = null
                };
            var add = function(series) {
                    var self = this,
                        singleSeries,
                        i;
                    if (!$.isArray(series))
                        series = [series];
                    for (i = 0; i < series.length; i++) {
                        singleSeries = series[i];
                        if (singleSeries.type.toLowerCase() === self.type)
                            self.series.push(singleSeries)
                    }
                };
            var adjustBarSeriesDimensionsCore = function(series, interval, stackCount, equalBarWidth, seriesStackIndexCallback) {
                    var spacing,
                        width,
                        maxWidth,
                        middleIndex,
                        stackIndex,
                        i,
                        point,
                        points,
                        seriesOffset,
                        stackName,
                        argumentsKeeper = {},
                        stackKeepers = {},
                        stacksWithArgument,
                        count,
                        round = Math.round;
                    if (equalBarWidth) {
                        width = equalBarWidth.width && equalBarWidth.width < 0 ? 0 : equalBarWidth.width;
                        spacing = equalBarWidth.spacing && equalBarWidth.spacing < 0 ? 0 : equalBarWidth.spacing;
                        if (width && !spacing)
                            if (stackCount > 1) {
                                spacing = round((interval * 0.7 - width * stackCount) / (stackCount - 1));
                                if (spacing < 1)
                                    spacing = 1
                            }
                            else
                                spacing = 0;
                        else if (spacing && !width) {
                            width = round((interval * 0.7 - spacing * (stackCount - 1)) / stackCount);
                            if (width < 2)
                                width = 2
                        }
                        else if (!spacing && !width) {
                            if (stackCount > 1) {
                                spacing = round(interval * 0.7 / stackCount * 0.2);
                                if (spacing < 1)
                                    spacing = 1
                            }
                            else
                                spacing = 0;
                            width = round((interval * 0.7 - spacing * (stackCount - 1)) / stackCount);
                            if (width < 2)
                                width = 2
                        }
                        if (width * stackCount + spacing * (stackCount - 1) > interval) {
                            spacing = round((interval * 0.7 - width * stackCount) / (stackCount - 1));
                            if (spacing < 1) {
                                spacing = 1;
                                maxWidth = round((interval * 0.7 - spacing * (stackCount - 1)) / stackCount)
                            }
                        }
                        middleIndex = stackCount / 2;
                        for (i = 0; i < series.length; i++) {
                            stackIndex = seriesStackIndexCallback(i);
                            points = series[i].getPoints();
                            seriesOffset = (stackIndex - middleIndex + 0.5) * (maxWidth || width) - (middleIndex - stackIndex - 0.5) * spacing;
                            $.each(points, function(_, point) {
                                point.correctCoordinates({
                                    width: width,
                                    offset: seriesOffset
                                })
                            })
                        }
                    }
                    else {
                        $.each(series, function(i, singleSeries) {
                            stackName = singleSeries.getStackName && singleSeries.getStackName();
                            stackName = stackName || i.toString();
                            if (!stackKeepers[stackName])
                                stackKeepers[stackName] = [];
                            stackKeepers[stackName].push(singleSeries)
                        });
                        $.each(series, function(i, singleSeries) {
                            $.each(singleSeries.getPoints(), function(_, point) {
                                var argument = point.argument;
                                if (!argumentsKeeper.hasOwnProperty(argument))
                                    argumentsKeeper[argument] = 1
                            })
                        });
                        for (var argument in argumentsKeeper) {
                            if (!argumentsKeeper.hasOwnProperty(argument))
                                continue;
                            stacksWithArgument = [];
                            $.each(stackKeepers, function(stackName, seriesInStack) {
                                $.each(seriesInStack, function(i, singleSeries) {
                                    point = singleSeries.getPointByArg(argument);
                                    if (point && point.value) {
                                        stacksWithArgument.push(stackName);
                                        return false
                                    }
                                })
                            });
                            count = stacksWithArgument.length;
                            spacing = round(interval * 0.7 / count * 0.2);
                            if (spacing < 1)
                                spacing = 1;
                            width = round((interval * 0.7 - spacing * (count - 1)) / count);
                            if (width < 2)
                                width = 2;
                            middleIndex = count / 2;
                            $.each(stackKeepers, function(stackName, seriesInStack) {
                                stackIndex = $.inArray(stackName, stacksWithArgument);
                                if (stackIndex === -1)
                                    return;
                                seriesOffset = (stackIndex - middleIndex + 0.5) * width - (middleIndex - stackIndex - 0.5) * spacing;
                                $.each(seriesInStack, function(i, singleSeries) {
                                    var point = singleSeries.getPointByArg(argument);
                                    if (point && point.value)
                                        point.correctCoordinates({
                                            width: width,
                                            offset: seriesOffset
                                        })
                                })
                            })
                        }
                    }
                };
            var adjustBarSeriesDimensions = function(translator) {
                    var debug = DX.utils.debug;
                    debug.assert(translator, 'translator was not passed or empty');
                    var self = this,
                        series = self.series,
                        equalBarWidth = self.equalBarWidth,
                        interval;
                    self.translator = translator;
                    interval = setInterval(self);
                    adjustBarSeriesDimensionsCore(series, interval, series.length, equalBarWidth, function(seriesIndex) {
                        return seriesIndex
                    })
                };
            var adjustStackedBarSeriesDimensions = function(translator) {
                    var debug = DX.utils.debug;
                    debug.assert(translator, 'translator was not passed or empty');
                    var self = this,
                        interval,
                        series = self.series,
                        stackIndexes = {},
                        stackCount = 0,
                        equalBarWidth = self.equalBarWidth;
                    $.each(series, function() {
                        var stackName = this.getStackName();
                        if (!stackIndexes.hasOwnProperty(stackName))
                            stackIndexes[stackName] = stackCount++
                    });
                    self.translator = translator;
                    interval = setInterval(self);
                    adjustBarSeriesDimensionsCore(series, interval, stackCount, equalBarWidth, function(seriesIndex) {
                        return stackIndexes[series[seriesIndex].getStackName()]
                    })
                };
            var adjustStackedSeriesValues = function() {
                    var self = this,
                        series = self.series,
                        stackKeepers = {
                            positive: {},
                            negative: {}
                        };
                    $.each(series, function(_, singleSeries) {
                        var points = singleSeries.getPoints();
                        $.each(points, function(index, point) {
                            var value = point.value,
                                argument = point.argument,
                                stackName = singleSeries.getStackName ? singleSeries.getStackName() : 'default',
                                valueType = value >= 0 ? 'positive' : 'negative',
                                currentStack;
                            stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
                            currentStack = stackKeepers[valueType][stackName];
                            if (currentStack[argument.valueOf()]) {
                                points[index].correctValue(currentStack[argument.valueOf()]);
                                currentStack[argument.valueOf()] += value
                            }
                            else
                                currentStack[argument.valueOf()] = value
                        })
                    });
                    setPercentStackedValues(series, stackKeepers, self.fullStacked)
                };
            var setPercentStackedValues = function(series, stackKeepers, fullStacked) {
                    $.each(series, function(_, singleSeries) {
                        var points = singleSeries.getPoints();
                        $.each(points, function(index, point) {
                            var value = point.value,
                                stackName = singleSeries.getStackName ? singleSeries.getStackName() : 'default',
                                valueType = value >= 0 ? 'positive' : 'negative',
                                currentStack;
                            stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
                            currentStack = stackKeepers[valueType][stackName];
                            points[index].setPercentValue(currentStack[point.argument.valueOf()], fullStacked)
                        })
                    })
                };
            var getMinShownBusinessValue = function(self, translator, minBarSize) {
                    var rotated = self.rotated,
                        canvas = translator.getCanvasVisibleArea();
                    if (minBarSize && !rotated)
                        return Math.abs(translator.untranslateY(canvas.minY) - translator.untranslateY(canvas.minY + minBarSize));
                    else if (minBarSize && rotated)
                        return Math.abs(translator.untranslateX(canvas.minX) - translator.untranslateX(canvas.minX + minBarSize))
                };
            var updateStackedSeriesValues = function(translator) {
                    var self = this,
                        series = self.series,
                        stackKeepers = {
                            positive: {},
                            negative: {}
                        };
                    $.each(series, function(_, singleSeries) {
                        var points = singleSeries.getPoints(),
                            minBarSize = singleSeries.styles && singleSeries.styles.minBarSize;
                        $.each(points, function(index, point) {
                            var value = point.value,
                                minValue = point.minValue,
                                argument = point.argument,
                                updateValue,
                                pointSize,
                                minShownBusinessValue,
                                stackName = singleSeries.getStackName ? singleSeries.getStackName() : 'default',
                                valueType = value >= 0 ? 'positive' : 'negative',
                                currentStack;
                            minShownBusinessValue = getMinShownBusinessValue(self, translator, minBarSize);
                            stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
                            currentStack = stackKeepers[valueType][stackName];
                            if (currentStack[argument.valueOf()]) {
                                pointSize = Math.abs(minValue - value);
                                if (minShownBusinessValue && pointSize < minShownBusinessValue && pointSize !== 0)
                                    updateValue = minShownBusinessValue;
                                else
                                    updateValue = Math.abs(value - minValue);
                                points[index].minValue = currentStack[argument.valueOf()];
                                points[index].value = currentStack[argument.valueOf()] + updateValue;
                                currentStack[argument.valueOf()] += updateValue
                            }
                            else {
                                pointSize = value;
                                if (minShownBusinessValue && pointSize < minShownBusinessValue && pointSize !== 0)
                                    updateValue = minShownBusinessValue;
                                else
                                    updateValue = value;
                                points[index].value = updateValue;
                                currentStack[argument.valueOf()] = updateValue
                            }
                        })
                    });
                    if (self.fullStacked)
                        updateFullStackedSeriesValues(series, stackKeepers)
                };
            var updateFullStackedSeriesValues = function(series, stackKeepers) {
                    $.each(series, function(_, singleSeries) {
                        var stackName = singleSeries.getStackName ? singleSeries.getStackName() : 'default',
                            points = singleSeries.getPoints();
                        $.each(points, function(index, point) {
                            var value = point.value,
                                argument = point.argument,
                                valueType = value >= 0 ? 'positive' : 'negative',
                                currentStack;
                            stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
                            currentStack = stackKeepers[valueType][stackName];
                            points[index].value = points[index].value / currentStack[argument.valueOf()] || 0;
                            if (DX.utils.isNumber(points[index].minValue))
                                points[index].minValue = points[index].minValue / currentStack[argument.valueOf()] || 0
                        })
                    })
                };
            var updateBarSeriesValues = function(translator) {
                    var self = this,
                        series = self.series,
                        rotated = self.rotated,
                        canvas = translator.getCanvasVisibleArea();
                    $.each(series, function(_, singleSeries) {
                        var points = singleSeries.getPoints(),
                            minBarSize = singleSeries.styles && singleSeries.styles.minBarSize;
                        $.each(points, function(index, point) {
                            var value = point.value,
                                updateValue,
                                pointSize,
                                minShownBusinessValue;
                            minShownBusinessValue = getMinShownBusinessValue(self, translator, minBarSize);
                            pointSize = Math.abs(value);
                            if (minShownBusinessValue && pointSize < minShownBusinessValue && pointSize !== 0)
                                updateValue = value > 0 ? minShownBusinessValue : -minShownBusinessValue;
                            else
                                updateValue = value;
                            points[index].value = updateValue
                        })
                    })
                };
            var adjuistCandlestickSeriesDimensions = function(translator) {
                    var debug = DX.utils.debug;
                    debug.assert(translator, 'translator was not passed or empty');
                    var self = this,
                        series = self.series,
                        interval;
                    self.translator = translator;
                    interval = setInterval(self);
                    adjustBarSeriesDimensionsCore(series, interval, series.length, true, function(seriesIndex) {
                        return seriesIndex
                    })
                };
            var setInterval = function(self) {
                    if (!self.rotated)
                        self.interval = self.translator.getIntervalX();
                    else
                        self.interval = self.translator.getIntervalY();
                    return self.interval
                };
            var adjustBubbleSeriesDimensions = function(translator) {
                    var debug = DX.utils.debug;
                    debug.assert(translator, 'translator was not passed or empty');
                    var self = this,
                        series = self.series,
                        points,
                        i,
                        minSize = 2,
                        maxSize = 0,
                        pointSize,
                        visibleArea = translator.getCanvasVisibleArea(),
                        min = Math.min(visibleArea.maxX - visibleArea.minX, visibleArea.maxY - visibleArea.minY);
                    for (i = 0; i < series.length; i++) {
                        points = series[i].getPoints();
                        $.each(points, function(_, point) {
                            maxSize = maxSize > point.size ? maxSize : point.size
                        })
                    }
                    for (i = 0; i < series.length; i++) {
                        points = series[i].getPoints();
                        $.each(points, function(_, point) {
                            pointSize = ~~(point.size * min * 0.1 / maxSize);
                            point.correctCoordinates(minSize < pointSize ? pointSize : minSize)
                        })
                    }
                };
            var preparePointsForSharedTooltip = function(tooltipOption) {
                    var stackPoints = [];
                    if (!tooltipOption.shared)
                        return;
                    $.each(this.series, function(i, singleSeries) {
                        var points = singleSeries.getPoints(),
                            stackName = singleSeries.getStackName();
                        $.each(points, function(index, point) {
                            var argument = point.argument,
                                argumentWithStackName = argument.valueOf() + ' ' + stackName;
                            if (!DX.utils.isArray(stackPoints[argumentWithStackName]))
                                stackPoints[argumentWithStackName] = [];
                            stackPoints[argumentWithStackName].push(point);
                            point.stackPoints = stackPoints[argumentWithStackName];
                            point.stackPoints.stackName = stackName
                        })
                    })
                };
            return {
                    ctor: ctor,
                    dispose: dispose,
                    add: add
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-core, file factory.js */
    (function($, DX) {
        var viz = DX.viz,
            core = viz.core,
            charts = viz.charts,
            series = charts.series;
        charts.factory = function() {
            var createSeries = function(seriesType, renderer, options) {
                    options = options || {};
                    options.specificType = null;
                    seriesType = (String(seriesType) || '').toLowerCase();
                    switch (seriesType.toLowerCase()) {
                        case'line':
                            return new series.LineSeries(renderer, options);
                        case'fullstackedline':
                            options.specificType = 'fullstackedline';
                            return new series.LineSeries(renderer, options);
                        case'stackedline':
                            options.specificType = 'stackedline';
                            return new series.LineSeries(renderer, options);
                        case'area':
                            return new series.AreaSeries(renderer, options);
                        case'fullstackedarea':
                            options.specificType = 'fullstackedarea';
                            return new series.AreaSeries(renderer, options);
                        case'stackedarea':
                            options.specificType = 'stackedarea';
                            return new series.AreaSeries(renderer, options);
                        case'bar':
                            return new series.BarSeries(renderer, options);
                        case'fullstackedbar':
                            options.specificType = 'fullstackedbar';
                            return new series.BarSeries(renderer, options);
                        case'stackedbar':
                            options.specificType = 'stackedbar';
                            return new series.BarSeries(renderer, options);
                        case'spline':
                            return new series.SplineSeries(renderer, options);
                        case'splinearea':
                            return new series.SplineAreaSeries(renderer, options);
                        case'scatter':
                            return new series.ScatterSeries(renderer, options);
                        case'candlestick':
                            return new series.CandleStickSeries(renderer, options);
                        case'stock':
                            return new series.StockSeries(renderer, options);
                        case'rangearea':
                            return new series.RangeAreaSeries(renderer, options);
                        case'rangebar':
                            return new series.RangeBarSeries(renderer, options);
                        case'pie':
                            return new series.PieSeries(renderer, options);
                        case'doughnut':
                        case'donut':
                            options.specificType = 'doughnut';
                            return new series.PieSeries(renderer, options);
                        case'stepline':
                            return new series.StepLineSeries(renderer, options);
                        case'steparea':
                            return new series.StepAreaSeries(renderer, options);
                        case'bubble':
                            return new series.BubbleSeries(renderer, options);
                        default:
                            return null
                    }
                };
            var createSeriesFamily = function(options) {
                    return new series.SeriesFamily(options)
                };
            var createAxis = function(renderer, options) {
                    return new charts.Axis(renderer, options)
                };
            var createRenderer = function(options) {
                    return new viz.renderers.Renderer(options)
                };
            var createThemeManager = function(options, groupName) {
                    return new charts.ThemeManager(options, groupName)
                };
            var createLegend = function(options, group, trackerGroup) {
                    return new charts.Legend(options, group, trackerGroup)
                };
            var createTooltip = function(options, group) {
                    return new charts.Tooltip(options, group)
                };
            var createLoadIndicator = function(options, group) {
                    return new charts.LoadIndicator(options, group)
                };
            var createDataValidator = function(data, groups, incidentOccured, dataPrepareOptions) {
                    return new charts.DataValidator(data, groups, incidentOccured, dataPrepareOptions)
                };
            var createTracker = function(options) {
                    return new charts.Tracker(options)
                };
            var createTitle = function(renderer, canvas, options, group) {
                    return new charts.ChartTitle(renderer, canvas, options, group)
                };
            var createChartLayoutManager = function() {
                    return new charts.LayoutManager
                };
            var getAxisTickProvider = function() {
                    return core.tickProvider
                };
            return {
                    createSeries: createSeries,
                    createSeriesFamily: createSeriesFamily,
                    createAxis: createAxis,
                    getAxisTickProvider: getAxisTickProvider,
                    createRenderer: createRenderer,
                    createThemeManager: createThemeManager,
                    createLegend: createLegend,
                    createTooltip: createTooltip,
                    createLoadIndicator: createLoadIndicator,
                    createDataValidator: createDataValidator,
                    createTracker: createTracker,
                    createChartLayoutManager: createChartLayoutManager,
                    createTitle: createTitle
                }
        }()
    })(jQuery, DevExpress);
    DevExpress.MOD_VIZ_CORE = true
}
if (!DevExpress.MOD_VIZ_CHARTS) {
    if (!window.DevExpress)
        throw Error('Required module is not referenced: core');
    if (!DevExpress.MOD_VIZ_CORE)
        throw Error('Required module is not referenced: viz-core');
    /*! Module viz-charts, file legend.js */
    (function($, DX, undefined) {
        DX.viz.charts.Legend = DX.Class.inherit({
            ctor: function(userOptions, group, trackerGroup) {
                this.legendGroup = group;
                this.trackerGroup = trackerGroup;
                this._init(userOptions)
            },
            update: function(userOptions) {
                this._init(userOptions)
            },
            _disposeTrackers: function() {
                var _this = this;
                $.each(_this.trackers || [], function(_, tracker) {
                    tracker.removeData()
                });
                _this.trackers = null
            },
            dispose: function() {
                var _this = this;
                _this._disposeTrackers();
                _this.labelFormatObject = null;
                _this.seriesGroups = null;
                _this.insideLegendGroup = null;
                _this.legendGroup = null;
                _this.trackerGroup = null;
                _this.renderer = null;
                _this.series = null;
                _this.options = null
            },
            _init: function(options) {
                var debug = DX.utils.debug;
                debug.assertParam(options.visible, 'Visibility was not passed');
                debug.assertParam(options.renderer, 'renderer was not passed');
                debug.assertParam(options.margin, 'margin was not passed');
                debug.assertParam(options.markerSize, 'markerSize was not passed');
                debug.assertParam(options.font.color, 'fontColor was not passed');
                debug.assertParam(options.font.family, 'fontFamily was not passed');
                debug.assertParam(options.font.size, 'fontSize was not passed');
                debug.assertParam(options.paddingLeftRight, 'paddingLeftRight was not passed');
                debug.assertParam(options.paddingTopBottom, 'paddingTopBottom was not passed');
                debug.assertParam(options.columnItemSpacing, 'columnItemSpacing was not passed');
                debug.assertParam(options.rowItemSpacing, 'rowItemSpacing was not passed');
                debug.assertParam(options.equalColumnWidth, 'equalColumnWidth was not passed');
                var i,
                    series = [];
                this.renderer = options.renderer;
                options.renderer = null;
                options.horizontalAlignment = (options.horizontalAlignment || '').toLowerCase();
                if (options.horizontalAlignment !== 'center' && options.horizontalAlignment !== 'right' && options.horizontalAlignment !== 'left')
                    options.horizontalAlignment = 'right';
                options.verticalAlignment = (options.verticalAlignment || '').toLowerCase();
                if (options.verticalAlignment !== 'top' && options.verticalAlignment !== 'bottom') {
                    if (options.horizontalAlignment === 'center')
                        options.verticalAlignment = 'bottom';
                    if (options.horizontalAlignment === 'right' || options.horizontalAlignment === 'left')
                        options.verticalAlignment = 'top'
                }
                options.layout = (options.layout || '').toLowerCase();
                if (options.layout !== 'horizontal' && options.layout !== 'vertical') {
                    if (options.horizontalAlignment === 'center')
                        options.layout = 'horizontal';
                    if (options.horizontalAlignment === 'right' || options.horizontalAlignment === 'left')
                        options.layout = 'vertical'
                }
                options.position = (options.position || '').toLowerCase();
                if (options.position !== 'outside' && options.position !== 'inside')
                    options.position = 'outside';
                options.hoverMode = (options.hoverMode || '').toLowerCase();
                options.customizeText = $.isFunction(options.customizeText) ? options.customizeText : function() {
                    return this.seriesName
                };
                this.series = $.map(options.series || [], function(series) {
                    if (series.options.showInLegend)
                        return series;
                    return null
                });
                options.series = null;
                this.options = options;
                this.__initialized = true
            },
            formatLabel: function(options) {
                return options.customizeText.call(this, this)
            },
            draw: function() {
                var self = this,
                    renderer = self.renderer,
                    options = self.options,
                    series = self.series || {},
                    x = 0,
                    y = 0,
                    seriesGroups = [],
                    i,
                    j,
                    label,
                    marker,
                    singleSeriesGroup,
                    markerSize = options.markerSize,
                    isHorizontal = options.layout === 'horizontal',
                    box,
                    labelBox,
                    cols = options.columnCount,
                    rows = options.rowCount,
                    horisontalTextPosition,
                    background,
                    equalColumnWidth = options.equalColumnWidth,
                    trackers = [],
                    labelText,
                    data,
                    legendBox,
                    autoEdit = false,
                    canvas = self.canvas,
                    borderVisible = options.border.visible && options.border.width && options.border.color && options.border.color !== 'none',
                    backgroundSettings,
                    hoverPattern,
                    selectedPattern,
                    hoverHatching,
                    selectedHatching,
                    states;
                if (!(options.visible && series && series.length)) {
                    self._disposeTrackers();
                    return
                }
                this.createClipRect();
                if (this.legendGroup) {
                    this.legendGroup.clear();
                    this.trackerGroup.clear();
                    this.legendGroup.move(0, 0);
                    this.trackerGroup.move(0, 0);
                    this.clipRect && this.legendGroup.applySettings({clipId: this.clipRect.id})
                }
                if (this.insideLegendGroup) {
                    this.insideLegendGroup.detach();
                    this.insideLegendGroup.remove();
                    this.insideLegendGroup = null
                }
                if (options.position === 'inside' || options.backgroundColor || borderVisible)
                    background = renderer.createRect(0, 0, 0, 0, 0, {
                        fill: options.backgroundColor || (options.position === 'inside' ? options.containerBackgroundColor : 'none'),
                        'class': 'dxc-border'
                    }).append(this.legendGroup);
                this.insideLegendGroup = renderer.createGroup().append(this.legendGroup);
                for (i = 0; i < series.length; i++) {
                    singleSeriesGroup = renderer.createGroup({'class': 'dxc-item'}).append(this.insideLegendGroup);
                    marker = renderer.createRect(x, y, markerSize, markerSize, 0, {
                        fill: series[i].styles.themeColor,
                        'class': series[i].className
                    }).append(singleSeriesGroup);
                    if (!series[i].markerPatterns) {
                        states = series[i].styles.states || series[i].options.states;
                        hoverHatching = $.extend({}, states.hover.hatching, {
                            step: 5,
                            width: 2
                        });
                        selectedHatching = $.extend({}, states.selected.hatching, {
                            step: 5,
                            width: 2
                        });
                        hoverPattern = states.hover.fill !== 'none' && hoverHatching.direction !== 'none' ? this.renderer.createPattern(states.hover.fill, hoverHatching).append() : {
                            id: series[i].styles.themeColor,
                            append: $.noop
                        };
                        selectedPattern = states.selected.fill !== 'none' && selectedHatching.direction !== 'none' ? this.renderer.createPattern(states.selected.fill, selectedHatching).append() : {
                            id: series[i].styles.themeColor,
                            append: $.noop
                        };
                        series[i].legend = this;
                        series[i].markerPatterns = {
                            marker: marker,
                            hoverPattern: hoverPattern,
                            selectedPattern: selectedPattern
                        }
                    }
                    else {
                        series[i].markerPatterns.hoverPattern.append();
                        series[i].markerPatterns.selectedPattern.append();
                        series[i].markerPatterns.marker.dispose();
                        series[i].markerPatterns.marker = marker
                    }
                    box = marker.getBBox();
                    if (!options.itemTextPosition)
                        horisontalTextPosition = !isHorizontal;
                    else
                        horisontalTextPosition = options.itemTextPosition === 'right';
                    self.labelFormatObject = {
                        seriesName: series[i].name,
                        seriesNumber: series[i].index,
                        seriesColor: series[i].styles.themeColor
                    };
                    labelText = self.formatLabel.call(self.labelFormatObject, options);
                    label = renderer.createText(labelText, horisontalTextPosition ? x + box.width + 7 : x, horisontalTextPosition ? y : y + box.height + 2, {
                        font: options.font,
                        align: !horisontalTextPosition ? 'center' : 'left'
                    }).append(singleSeriesGroup);
                    labelBox = label.getBBox();
                    if (horisontalTextPosition)
                        label.move(0, ~~(box.y + box.height / 2 - (labelBox.y + labelBox.height / 2)));
                    else
                        label.move(~~(box.x + box.width / 2 - (labelBox.x + labelBox.width / 2)), box.y + box.height + 2 - labelBox.y);
                    trackers.push(renderer.createRect(0, 0, 0, 0, 0, {
                        stroke: 'none',
                        fill: 'grey',
                        opacity: 0.0001,
                        inh: true
                    }));
                    seriesGroups.push(singleSeriesGroup)
                }
                if (cols && !rows)
                    rows = Math.ceil(series.length / cols);
                else if (!cols && rows)
                    cols = Math.ceil(series.length / rows);
                else if (cols && rows) {
                    if (isHorizontal && cols < Math.ceil(series.length / rows))
                        cols = Math.ceil(series.length / rows);
                    else if (!isHorizontal && rows < Math.ceil(series.length / cols))
                        rows = Math.ceil(series.length / cols)
                }
                else {
                    autoEdit = true;
                    if (isHorizontal) {
                        rows = 1;
                        cols = series.length
                    }
                    else {
                        cols = 1;
                        rows = series.length
                    }
                }
                data = self.getDataRowsColumns(seriesGroups, cols, rows);
                self.moveItems(data, seriesGroups, this.insideLegendGroup, horisontalTextPosition, trackers);
                if (autoEdit && rows === 1) {
                    legendBox = this.insideLegendGroup.getBBox();
                    while (legendBox.width > canvas.width - canvas.right - canvas.left && cols > 1) {
                        cols = Math.ceil(cols / 2);
                        rows = Math.ceil(series.length / cols);
                        data = self.getDataRowsColumns(seriesGroups, cols, rows);
                        self.moveItems(data, seriesGroups, this.insideLegendGroup, horisontalTextPosition, trackers);
                        legendBox = this.insideLegendGroup.getBBox()
                    }
                }
                else if (autoEdit && cols === 1) {
                    legendBox = this.insideLegendGroup.getBBox();
                    while (legendBox.height > canvas.height - canvas.top - canvas.bottom && rows > 1) {
                        rows = Math.ceil(rows / 2);
                        cols = Math.ceil(series.length / rows);
                        data = self.getDataRowsColumns(seriesGroups, cols, rows);
                        self.moveItems(data, seriesGroups, this.insideLegendGroup, horisontalTextPosition, trackers);
                        legendBox = this.insideLegendGroup.getBBox()
                    }
                }
                if (background) {
                    legendBox = this.legendGroup.getBBox();
                    backgroundSettings = {
                        x: Math.round(legendBox.x),
                        y: Math.round(legendBox.y),
                        width: Math.round(legendBox.width) + 2 * options.paddingLeftRight,
                        height: Math.round(legendBox.height) + 2 * options.paddingTopBottom
                    };
                    if (borderVisible) {
                        backgroundSettings.strokeWidth = options.border.width;
                        backgroundSettings.stroke = options.border.color;
                        backgroundSettings.strokeOpacity = options.border.opacity;
                        backgroundSettings.dashStyle = options.border.dashStyle;
                        backgroundSettings.rx = options.border.cornerRadius || 0;
                        backgroundSettings.ry = options.border.cornerRadius || 0
                    }
                    background.applySettings(backgroundSettings);
                    self.insideLegendGroup.move(options.paddingLeftRight, options.paddingTopBottom);
                    $.each(trackers, function(_, tracker) {
                        tracker.move(options.paddingLeftRight, options.paddingTopBottom)
                    })
                }
                self.seriesGroups = seriesGroups;
                self.trackers = trackers;
                self.drawTrackers()
            },
            drawTrackers: function() {
                var _this = this;
                $.each(_this.trackers || [], function(i, tracker) {
                    tracker.data({
                        series: _this.series[i],
                        mode: _this.options.hoverMode
                    });
                    tracker.append(_this.trackerGroup)
                })
            },
            applyNormalStyle: function(series) {
                if (series.markerPatterns)
                    series.markerPatterns.marker.applySettings({fill: series.styles.themeColor})
            },
            applyHoverStyle: function(series) {
                if (series.markerPatterns)
                    series.markerPatterns.marker.applySettings({fill: series.markerPatterns.hoverPattern.id})
            },
            applySelectionStyle: function(series) {
                if (series.markerPatterns)
                    series.markerPatterns.marker.applySettings({fill: series.markerPatterns.selectedPattern.id})
            },
            getDataRowsColumns: function(seriesGroups, cols, rows) {
                var self = this,
                    i,
                    j,
                    options = self.options,
                    equalColumnWidth = options.equalColumnWidth,
                    series = self.series || {},
                    maxWidthPerColumn = [],
                    maxWidthColumn = 0,
                    maxHeightRow = 0,
                    group,
                    box;
                for (i = 0; i < cols; i++)
                    maxWidthPerColumn[i] = 0;
                for (i = 0; i < rows; i++)
                    for (j = 0; j < cols; j++) {
                        if (rows < cols)
                            group = seriesGroups[i * cols + j];
                        else
                            group = seriesGroups[i + j * rows];
                        if (!group)
                            break;
                        box = group.getBBox();
                        if (maxHeightRow < box.height)
                            maxHeightRow = box.height;
                        if (!equalColumnWidth) {
                            if (maxWidthPerColumn[j] < box.width)
                                maxWidthPerColumn[j] = box.width
                        }
                        else if (maxWidthColumn < box.width)
                            maxWidthColumn = box.width
                    }
                return {
                        rows: rows,
                        cols: cols,
                        maxWidthPerColumn: maxWidthPerColumn,
                        maxWidthColumn: maxWidthColumn,
                        maxHeightRow: maxHeightRow
                    }
            },
            moveItems: function(data, seriesGroups, insideLegendGroup, horisontalTextPosition, trackers) {
                var self = this,
                    i,
                    j,
                    rows,
                    cols,
                    number,
                    group,
                    box,
                    xShift = 0,
                    yShift = 0,
                    widthColumn,
                    options = self.options,
                    xPadding = options.columnItemSpacing,
                    yPadding = options.rowItemSpacing,
                    equalColumnWidth = options.equalColumnWidth,
                    renderer = self.renderer,
                    maxWidthPerColumn = [],
                    maxWidthColumn = 0,
                    maxHeightRow = 0;
                rows = data.rows;
                cols = data.cols;
                maxHeightRow = data.maxHeightRow;
                maxWidthColumn = data.maxWidthColumn;
                maxWidthPerColumn = data.maxWidthPerColumn;
                for (i = 0; i < rows; i++) {
                    for (j = 0; j < cols; j++) {
                        if (rows < cols)
                            number = i * cols + j;
                        else
                            number = i + j * rows;
                        group = seriesGroups[number];
                        if (!group)
                            break;
                        box = group.getBBox();
                        widthColumn = !equalColumnWidth ? maxWidthPerColumn[j] : maxWidthColumn;
                        if (horisontalTextPosition) {
                            group.move(xShift - box.x, yShift);
                            trackers[number].applySettings({
                                x: xShift - xPadding / 2,
                                y: yShift + box.y - yPadding / 2,
                                height: maxHeightRow + yPadding,
                                width: widthColumn + xPadding
                            })
                        }
                        else {
                            group.move(xShift - box.x - box.width / 2 + widthColumn / 2, yShift);
                            trackers[number].applySettings({
                                x: xShift - xPadding / 2,
                                y: yShift + box.y - yPadding / 2,
                                height: maxHeightRow + yPadding,
                                width: widthColumn + xPadding
                            })
                        }
                        xShift = xShift + widthColumn + xPadding
                    }
                    yShift = yShift + maxHeightRow + yPadding;
                    xShift = 0
                }
            },
            getBoundingRect: function() {
                if (this.legendGroup)
                    return this.legendGroup.getBBox();
                return {}
            },
            toForeground: function() {
                this.legendGroup && this.legendGroup.toForeground()
            },
            createClipRect: function() {
                var canvas = this.canvas;
                if (canvas)
                    if (!this.clipRect)
                        this.clipRect = this.renderer.createClipRect(canvas.left, canvas.top, canvas.width - canvas.left - canvas.right, canvas.height - canvas.top - canvas.bottom).append();
                    else
                        this.clipRect.updateRectangle({
                            x: canvas.left,
                            y: canvas.top,
                            width: canvas.width - canvas.left - canvas.right,
                            height: canvas.height - canvas.top - canvas.bottom
                        })
            },
            updateClip: function(settings) {
                this.clipRect && this.clipRect.updateRectangle({
                    translateX: -settings.translateX,
                    translateY: -settings.translateY
                });
                this.legendGroup.update()
            },
            shift: function(x, y) {
                var settings = {};
                x && (settings.translateX = x);
                y && (settings.translateY = y);
                this.legendGroup.applySettings(settings);
                this.trackerGroup.applySettings(settings);
                this.updateClip(settings)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-charts, file chartTitle.js */
    (function($, DX, undefined) {
        var isDefined = DX.utils.isDefined,
            endsWith = function(value, pattern) {
                return value.substr(value.length - pattern.length) === pattern
            },
            startsWith = function(value, pattern) {
                return value.indexOf(pattern) === 0
            };
        DX.viz.charts.ChartTitle = DX.Class.inherit({
            ctor: function(renderer, canvas, options, group) {
                var _this = this;
                _this._init(canvas, options);
                _this.renderer = renderer;
                _this.clipRect = _this.createClipRect();
                _this.titleGroup = group;
                _this.titleGroup && _this.clipRect && _this.titleGroup.applySettings({clipId: _this.clipRect.id})
            },
            dispose: function() {
                var _this = this;
                _this.renderer = null;
                _this.clipRect = null;
                _this.title = null;
                _this.innerTitleGroup = null;
                _this.titleGroup = null;
                _this.options = null;
                _this.canvas = null
            },
            update: function(canvas, options) {
                this._init(canvas, options)
            },
            _init: function(canvas, options) {
                var _this = this;
                if (options) {
                    _this._parseAlignments(options);
                    _this.horizontalAlignment = options.horizontalAlignment;
                    _this.verticalAlignment = options.verticalAlignment;
                    _this.options = options
                }
                _this.canvas = canvas || _this.canvas
            },
            _parseAlignments: function(options) {
                if (isDefined(options.position) && !(isDefined(options.verticalAlignment) && isDefined(options.horizontalAlignment))) {
                    options.position = options.position.toLowerCase();
                    options.verticalAlignment = endsWith(options.position, 'top') ? 'top' : 'bottom';
                    options.horizontalAlignment = startsWith(options.position, 'left') ? 'left' : startsWith(options.position, 'center') && 'center' || 'right';
                    return
                }
                options.verticalAlignment = (options.verticalAlignment || '').toLowerCase();
                options.horizontalAlignment = (options.horizontalAlignment || '').toLowerCase();
                if (options.verticalAlignment !== 'top' && options.verticalAlignment !== 'bottom')
                    options.verticalAlignment = 'top';
                if (options.horizontalAlignment !== 'left' && options.horizontalAlignment !== 'center' && options.horizontalAlignment !== 'right')
                    options.horizontalAlignment = 'center'
            },
            render: function() {
                var _this = this,
                    titleOptions = _this.options,
                    renderer = _this.renderer,
                    attr;
                if (!titleOptions.text)
                    return;
                if (!_this.innerTitleGroup)
                    _this.innerTitleGroup = renderer.createGroup();
                else
                    _this.innerTitleGroup.clear();
                _this.innerTitleGroup.append(_this.titleGroup);
                attr = {
                    font: titleOptions.font,
                    align: _this.horizontalAlignment,
                    style: titleOptions.fontStyle
                };
                _this.title = renderer.createText(titleOptions.text, _this.canvas.left, _this.canvas.top, attr).append(_this.innerTitleGroup);
                _this.title.text = titleOptions.text;
                _this.correctTitleLength()
            },
            correctTitleLength: function() {
                var _this = this,
                    canvas = _this.canvas,
                    text = _this.title.text,
                    updateText,
                    lineLength,
                    canvasWidth = canvas.width - canvas.right - canvas.left,
                    box = _this.getBoundingRect();
                if (canvasWidth > box.width || text.indexOf("<br/>") != -1)
                    return;
                lineLength = text.length * canvasWidth / box.width;
                updateText = text.substr(0, ~~lineLength - 1 - 3) + "...";
                _this.title.updateText(updateText);
                _this.title.text = updateText
            },
            getBoundingRect: function() {
                var options = this.options,
                    box;
                if (!this.innerTitleGroup)
                    return {
                            width: 0,
                            height: 0,
                            x: 0,
                            y: 0
                        };
                box = this.innerTitleGroup.getBBox();
                if (isDefined(options.placeholderSize))
                    box.height = options.placeholderSize;
                return box
            },
            shift: function(x, y) {
                this.innerTitleGroup.move(x, y)
            },
            createClipRect: function() {
                if (isDefined(this.options.placeholderSize))
                    return this.renderer.createClipRect(0, 0, 0, 0)
            },
            setClipRectSettings: function() {
                var canvas = this.canvas,
                    verticalAlignment = this.verticalAlignment,
                    clipRect = this.clipRect;
                if (clipRect) {
                    clipRect.append();
                    if (verticalAlignment === 'top')
                        clipRect.updateRectangle({
                            x: 0,
                            y: 0,
                            width: canvas.width,
                            height: canvas.top
                        });
                    else if (verticalAlignment === 'bottom')
                        clipRect.updateRectangle({
                            x: 0,
                            y: canvas.height - canvas.bottom,
                            width: canvas.width,
                            height: canvas.bottom
                        })
                }
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-charts, file axis.js */
    (function($, DX, undefined) {
        var utils = DX.utils,
            mathAbs = Math.abs,
            core = DX.viz.core,
            ParseUtils = core.ParseUtils,
            AXIS_VALUE_MARGIN_PRIORITY = 100,
            DEFAULT_AXIS_LABEL_SPACING = 5,
            AXIS_STAGGER_OVERLAPPING_KOEF = 2,
            MAX_GRID_BORDER_ADHENSION = 4,
            CANVAS_POSITION_PREFIX = 'canvas_position_',
            CANVAS_POSITION_BOTTOM = 'canvas_position_bottom',
            CANVAS_POSITION_TOP = 'canvas_position_top',
            CANVAS_POSITION_LEFT = 'canvas_position_left',
            CANVAS_POSITION_RIGHT = 'canvas_position_right';
        DX.viz.charts.AXIS_STAGGER_OVERLAPPING_KOEF = AXIS_STAGGER_OVERLAPPING_KOEF;
        DX.viz.charts.Axis = DX.Class.inherit(function() {
            var ctor = function(renderer, options) {
                    var debug = DX.utils.debug;
                    debug.assertParam(renderer, 'renderer was not passed');
                    debug.assertParam(options.label, 'label was not passed');
                    debug.assertParam(options.tick, 'tick was not passed');
                    debug.assertParam(options.grid, 'grid was not passed');
                    debug.assertParam(options.title, 'title was not passed');
                    debug.assert(options.axisDivisionFactor, 'axisDivisionFactor was not passed');
                    debug.assert(options.stripStyle, 'stripStyle was not passed');
                    debug.assert(options.constantLineStyle, 'constantLineStyle was not passed');
                    debug.assert(options.position, 'position was not passed');
                    debug.assertParam(options.isHorizontal, 'isHorizontal was not passed');
                    this.renderer = renderer;
                    this.init(options);
                    this._$axis = $(this)
                };
            var dispose = function() {
                    var _this = this;
                    _this._axisElementsGroup && _this._axisElementsGroup.dispose();
                    $.each(_this.labels || [], function(_, label) {
                        label.removeData()
                    });
                    _this._$axis = null;
                    _this.labels = null;
                    _this.title = null;
                    _this.stripLabels = null;
                    _this.stripRects = null;
                    _this.constantLineLabels = null;
                    _this.constantLines = null;
                    _this._axisStripGroup = null;
                    _this._axisConstantLineGroup = null;
                    _this._axisLineGroup = null;
                    _this._axisElementsGroup = null;
                    _this._axisGridGroup = null;
                    _this._axisGroup = null;
                    _this.axesContainerGroup = null;
                    _this.stripsGroup = null;
                    _this.constantLinesGroup = null;
                    _this.renderer = null;
                    _this.translator = null;
                    _this.options = null;
                    _this.textOptions = null;
                    _this._tickValues = null;
                    _this._fullTickValues = null;
                    _this._fullTickPositions = null
                };
            var init = function(options) {
                    var categories = options.categories,
                        labelOptions = options.label;
                    options.hoverMode = options.hoverMode ? options.hoverMode.toLowerCase() : 'none';
                    this.hasLabelFormat = labelOptions.format !== '' && utils.isDefined(labelOptions.format);
                    this.options = options;
                    this.staggered = labelOptions.staggered;
                    labelOptions.minSpacing = utils.isDefined(labelOptions.minSpacing) ? labelOptions.minSpacing : DEFAULT_AXIS_LABEL_SPACING;
                    processCustomOptions(options);
                    if (categories) {
                        this.labelsNumber = categories.length;
                        this.ticksNumber = this.labelsNumber
                    }
                    options.range = {
                        min: options.min,
                        max: options.max,
                        categories: options.categories && options.categories.slice(0)
                    };
                    this.pane = options.pane;
                    this.textOptions = {
                        align: labelOptions.alignment,
                        font: labelOptions.font,
                        opacity: labelOptions.opacity,
                        style: labelOptions.style
                    };
                    if (options.type === 'logarithmic')
                        this.calcInterval = function(value, prevValue) {
                            return utils.getLog(value / prevValue, options.logarithmBase)
                        };
                    else
                        this.calcInterval = function(value, prevValue) {
                            return value - prevValue
                        }
                };
            var updateTranslatorInterval = function(self) {
                    var i,
                        tickValues,
                        options = self.options,
                        businessRange = self.translator.getBusinessRange(),
                        interval;
                    if (businessRange && businessRange.getBoundRange && !options.categories) {
                        tickValues = self.getTickValues();
                        for (i = 0; i < tickValues.length - 1; i++) {
                            interval = mathAbs(tickValues[i] - tickValues[i + 1]);
                            if (options.isHorizontal)
                                businessRange.getBoundRange({intervalX: interval});
                            else
                                businessRange.getBoundRange({intervalY: interval})
                        }
                    }
                };
            var setTranslator = function(translator) {
                    var debug = DX.utils.debug;
                    debug.assertParam(translator, 'translator was not passed');
                    this.translator = translator;
                    this.resetTicks();
                    updateTranslatorInterval(this)
                };
            var resetTicks = function() {
                    this._tickValues = this._tickPositions = this._fullTickValues = this._fullTickPositions = null
                };
            var setRange = function(range) {
                    var debug = DX.utils.debug;
                    debug.assertParam(range, 'range was not passed');
                    var self = this,
                        options = self.options;
                    if (options.isHorizontal) {
                        options.min = range.minVisibleX;
                        options.max = range.maxVisibleX;
                        options.categories = range.categoriesX;
                        options.stubData = range.stubDataX
                    }
                    else {
                        options.min = range.minVisibleY;
                        options.max = range.maxVisibleY;
                        options.categories = range.categoriesY;
                        options.stubData = range.stubDataY
                    }
                    this.resetTicks()
                };
            var processCustomOptions = function(options) {
                    var label = options.label,
                        left = 'left',
                        right = 'right',
                        top = 'top',
                        bottom = 'bottom';
                    if (options.isHorizontal) {
                        if (!(options.position === bottom || options.position === top))
                            options.position = bottom
                    }
                    else if (!(options.position === left || options.position === right))
                        options.position = left;
                    if (options.position === right) {
                        label.indentFromAxis *= -1;
                        if (!label.userAlignment)
                            label.alignment = left
                    }
                    if (options.position === top)
                        label.indentFromAxis *= -1
                };
            var getXAxisPosition = function(self) {
                    var delta = 0;
                    if (self.delta)
                        delta = self.delta[self.options.position] || 0;
                    return self.translator.translateX(CANVAS_POSITION_PREFIX + self.options.position) + delta
                };
            var getYAxisPosition = function(self) {
                    var delta = 0;
                    if (self.delta)
                        delta = self.delta[self.options.position] || 0;
                    return self.translator.translateY(CANVAS_POSITION_PREFIX + self.options.position) + delta
                };
            var drawAxis = function drawAxis(self, group) {
                    var translator = self.translator,
                        options = self.options,
                        lineOptions = options,
                        axisAttr = {
                            strokeWidth: lineOptions.width,
                            stroke: lineOptions.color,
                            strokeOpacity: lineOptions.opacity
                        },
                        axis,
                        axisPosition = self.axisPosition,
                        start,
                        end;
                    if (!lineOptions.visible)
                        return;
                    if (self.options.isHorizontal) {
                        if (options.categories) {
                            start = translator.translateX(CANVAS_POSITION_LEFT);
                            end = translator.translateX(CANVAS_POSITION_RIGHT)
                        }
                        else {
                            start = translator.translateX(options.min);
                            end = translator.translateX(options.max)
                        }
                        axis = self.renderer.createLine(start, axisPosition, end, axisPosition, axisAttr)
                    }
                    else {
                        if (options.categories) {
                            start = translator.translateY(CANVAS_POSITION_TOP);
                            end = translator.translateY(CANVAS_POSITION_BOTTOM)
                        }
                        else {
                            start = translator.translateY(options.min);
                            end = translator.translateY(options.max)
                        }
                        axis = self.renderer.createLine(axisPosition, start, axisPosition, end, axisAttr)
                    }
                    axis.append(group)
                };
            var _getOptimalRotationAngle = function(tick1, tick2, labelOptions) {
                    var self = this,
                        svgElement1 = self.renderer.createText(formatLabel(tick1, labelOptions), core.outOfScreen.x + self.translator.translateX(tick1), core.outOfScreen.y, self.textOptions).append(),
                        svgElement2 = self.renderer.createText(formatLabel(tick2, labelOptions), core.outOfScreen.x + self.translator.translateX(tick2), core.outOfScreen.y, self.textOptions).append(),
                        bBox1 = svgElement1.getBBox(),
                        bBox2 = svgElement2.getBBox(),
                        angle = Math.asin((bBox1.height + labelOptions.minSpacing) / (bBox2.x - bBox1.x)) * 180 / Math.PI;
                    svgElement1.remove();
                    svgElement2.remove();
                    return isNaN(angle) ? 90 : Math.ceil(angle)
                };
            var _applyOptimalOverlappingBehavior = function(ticks, ticksOptions) {
                    function nextState(state) {
                        switch (state) {
                            case'overlap':
                                return 'stagger';
                            case'stagger':
                                return 'rotate';
                            case'rotate':
                            default:
                                return 'end'
                        }
                    }
                    var self = this,
                        isOverlapped = false,
                        rotationAngle = null,
                        mode = null,
                        options = $.extend({}, ticksOptions),
                        state = 'overlap';
                    while (state !== 'end') {
                        isOverlapped = self.options.tickProvider.isOverlappedTicks(ticks, options);
                        isOverlapped = rotationAngle && rotationAngle !== 90 ? false : isOverlapped;
                        state = nextState(isOverlapped ? state : null);
                        self.testAutoOverlappingState = state;
                        switch (state) {
                            case'stagger':
                                options.screenDelta *= AXIS_STAGGER_OVERLAPPING_KOEF;
                                mode = state;
                                break;
                            case'rotate':
                                rotationAngle = self._getOptimalRotationAngle(ticks[0], ticks[1], self.options.label);
                                self.testAutoOverlappingRotationAngle = rotationAngle;
                                options.screenDelta = ticksOptions.screenDelta;
                                options.textOptions.rotate = rotationAngle;
                                mode = state;
                                break
                        }
                    }
                    self.testAutoOverlappingOptions = options;
                    self.overlappingBehavior.isOverlapped = isOverlapped;
                    self.overlappingBehavior.mode = mode;
                    self.overlappingBehavior.rotationAngle = rotationAngle
                };
            var getTicksOptions = function(self, options, getPosition) {
                    var bpRange = options.isHorizontal ? [CANVAS_POSITION_LEFT, CANVAS_POSITION_RIGHT] : [CANVAS_POSITION_BOTTOM, CANVAS_POSITION_TOP],
                        screenDelta = mathAbs(getPosition.call(self.translator, bpRange[1]) - getPosition.call(self.translator, bpRange[0])),
                        digitPosition = utils.getSignificantDigitPosition(mathAbs(options.max - options.min) / screenDelta),
                        correctingValue,
                        min = options.min,
                        max = options.max,
                        base;
                    if (options.type === 'logarithmic')
                        base = options.logarithmBase;
                    if (utils.isNumber(min) && options.type !== 'logarithmic') {
                        min = utils.roundValue(options.min, digitPosition);
                        if (min < options.min) {
                            correctingValue = Math.pow(10, -digitPosition);
                            min = utils.applyPrecisionByMinDelta(min, correctingValue, min + correctingValue)
                        }
                        if (min > max)
                            min = options.min
                    }
                    return {
                            min: min,
                            max: max,
                            base: base,
                            type: options.type,
                            customTicks: $.isArray(options.categories) ? options.categories : self._tickValues,
                            useTicksAutoArrangement: false,
                            textOptions: self.textOptions,
                            getText: function(value) {
                                return formatLabel(value, options.label)
                            },
                            renderer: self.renderer,
                            textSpacing: self.options.label.minSpacing,
                            translator: self.translator,
                            tickInterval: self.options.stubData ? null : options.tickInterval,
                            screenDelta: screenDelta,
                            gridSpacingFactor: options.axisDivisionFactor,
                            isHorizontal: options.isHorizontal,
                            setTicksAtUnitBeginning: options.setTicksAtUnitBeginning,
                            incidentOccured: options.incidentOccured
                        }
                };
            var getTickValues = function() {
                    var self = this,
                        correctedScreenDelta,
                        options = self.options,
                        getPosition = options.isHorizontal ? self.translator.translateX : self.translator.translateY,
                        tickProvider = options.tickProvider,
                        labelOptions = options.label,
                        categories = options.categories,
                        ticksOptions;
                    ticksOptions = getTicksOptions(self, options, getPosition);
                    self._fullTickValues = self._tickValues = tickProvider.getTicks(ticksOptions);
                    if ((utils.isDate(options.min) || utils.isDate(categories && categories[0])) && !self.hasLabelFormat)
                        options.label.format = DX.formatHelper.getDateFormatByTicks(self._tickValues);
                    self.overlappingBehavior = labelOptions.overlappingBehavior ? $.extend({}, labelOptions.overlappingBehavior) : null;
                    if (self.overlappingBehavior) {
                        if (!options.isHorizontal && self.overlappingBehavior.mode !== 'enlargeTickInterval')
                            self.overlappingBehavior.mode = 'ignore';
                        ticksOptions.useTicksAutoArrangement = self.overlappingBehavior.mode !== 'ignore';
                        if (self.overlappingBehavior.mode === 'auto') {
                            self.textOptions.rotate = 0;
                            self._applyOptimalOverlappingBehavior(self._fullTickValues, ticksOptions);
                            ticksOptions.useTicksAutoArrangement = self.overlappingBehavior.isOverlapped
                        }
                        if (self.overlappingBehavior.mode === 'rotate') {
                            self.textOptions.rotate = self.overlappingBehavior.rotationAngle;
                            if (!labelOptions.userAlignment)
                                self.textOptions.align = 'left'
                        }
                        else if (!labelOptions.userAlignment)
                            self.textOptions.align = labelOptions.alignment
                    }
                    if (ticksOptions.useTicksAutoArrangement) {
                        correctedScreenDelta = self._tickValues.length ? getPosition.call(self.translator, self._tickValues[self._tickValues.length - 1]) - getPosition.call(self.translator, self._tickValues[0]) : null;
                        if (correctedScreenDelta) {
                            ticksOptions.screenDelta = Math.abs(correctedScreenDelta);
                            ticksOptions.ticksCount = self._tickValues.length - 1
                        }
                        else
                            ticksOptions.ticksCount = self._tickValues.length;
                        if (self.overlappingBehavior && self.overlappingBehavior.mode === 'stagger')
                            ticksOptions.screenDelta *= AXIS_STAGGER_OVERLAPPING_KOEF;
                        ticksOptions.customTicks = self._tickValues;
                        self._tickValues = tickProvider.getTicks(ticksOptions)
                    }
                    self._testTKScreenDelta = ticksOptions.screenDelta;
                    self._autoArrangementStep = self._tickValues.autoArrangementStep;
                    self._useTicksAutoArrangement = ticksOptions.useTicksAutoArrangement;
                    if (self.options.stubData) {
                        self._testSkippedFormattingAndOverlapping = true;
                        return self._tickValues
                    }
                    if (!$.isArray(categories))
                        self._fullTickValues = self._tickValues;
                    return self._tickValues
                };
            var setTickValues = function(tickValues) {
                    this.resetTicks();
                    this._fullTickValues = this._tickValues = tickValues
                };
            var prepareLabelsToDraw = function prepareLabelsToDraw(self) {
                    var options = self.options,
                        ticksValues,
                        ticks = [],
                        getPosition,
                        i;
                    if (options.isHorizontal)
                        getPosition = self.translator.translateX;
                    else
                        getPosition = self.translator.translateY;
                    ticksValues = self.getTickValues();
                    if (ticksValues.hideLabels || options.stubData)
                        ticks.hideLabels = true;
                    for (i = 0; i < ticksValues.length; i++)
                        ticks.push({
                            text: ticksValues[i],
                            pos: getPosition.call(self.translator, ticksValues[i])
                        });
                    return ticks
                };
            var correctTicksPosition = function(self, ticks) {
                    var options = self.options,
                        translator = self.translator,
                        tickDelta,
                        i;
                    if (options.categories && (options.discreteAxisDivisionMode !== 'crossLabels' || !options.discreteAxisDivisionMode)) {
                        if (options.isHorizontal) {
                            tickDelta = translator.getIntervalX() / 2;
                            if (!options.valueMarginsEnabled)
                                ticks = ticks.slice(0, ticks.length - 1)
                        }
                        else {
                            tickDelta = -translator.getIntervalY() / 2;
                            if (!options.valueMarginsEnabled)
                                ticks = ticks.slice(1, ticks.length)
                        }
                        for (i = 0; i < ticks.length; i++)
                            ticks[i].pos = ticks[i].pos + tickDelta
                    }
                    return ticks
                };
            var prepareFullTicksToDraw = function prepareFullTicksToDraw(self) {
                    var options = self.options,
                        ticksValues = self._fullTickValues,
                        ticks = [],
                        getPosition = options.isHorizontal ? self.translator.translateX : self.translator.translateY,
                        i;
                    if (!self._fullTickPositions) {
                        if (!ticksValues) {
                            self.getTickValues();
                            ticksValues = self._fullTickValues || []
                        }
                        for (i = 0; i < ticksValues.length; i++)
                            ticks.push({pos: getPosition.call(self.translator, ticksValues[i])});
                        self._fullTickPositions = correctTicksPosition(self, ticks)
                    }
                    return self._fullTickPositions
                };
            var drawTicks = function drawTicks(self, group) {
                    var renderer = self.renderer,
                        options = self.options,
                        ticksOptions = options.tick,
                        categories = options.categories,
                        tickDelta = options.discreteAxisDivisionMode === 'crossLabels' ? 0 : 0.5,
                        i,
                        defaultTickLength = 8,
                        attr = {
                            strokeWidth: 1,
                            stroke: ticksOptions.color,
                            strokeOpacity: ticksOptions.opacity
                        },
                        currentTickConstant,
                        axisPosition = self.axisPosition,
                        tickPositionStart,
                        tickPositionEnd,
                        tick,
                        ticksToDraw;
                    if (!ticksOptions.visible)
                        return;
                    ticksToDraw = prepareFullTicksToDraw(self);
                    if (self.options.isHorizontal)
                        for (i = 0; i < ticksToDraw.length; i++) {
                            tick = ticksToDraw[i];
                            renderer.createLine(tick.pos, axisPosition - defaultTickLength / 2, tick.pos, axisPosition + defaultTickLength / 2, attr).append(group)
                        }
                    else
                        for (i = 0; i < ticksToDraw.length; i++) {
                            tick = ticksToDraw[i];
                            renderer.createLine(axisPosition - defaultTickLength / 2, tick.pos, axisPosition + defaultTickLength / 2, tick.pos, attr).append(group)
                        }
                };
            var formatLabel = function formatLabel(value, options) {
                    var formatObject = {
                            value: value,
                            valueText: DX.formatHelper.format(value, options.format, options.precision) || ''
                        };
                    return options.customizeText ? options.customizeText.call(formatObject, formatObject) : formatObject.valueText
                };
            var setPercentLabelFormat = function() {
                    var labelOptions = this.options.label;
                    if (!labelOptions.format) {
                        labelOptions.format = 'percent';
                        labelOptions.autoFormat = true
                    }
                };
            var resetAutoLabelFormat = function() {
                    var labelOptions = this.options.label;
                    if (labelOptions.autoFormat) {
                        delete labelOptions.format;
                        delete labelOptions.autoFormat
                    }
                };
            var createTextForVerticalLabels = function(text, y, x, textOptions) {
                    return this.createText(text, x, y, textOptions)
                };
            var drawLabels = function drawLabels(self, group) {
                    var i,
                        options = self.options,
                        categories = options.categories,
                        renderer = self.renderer,
                        axisPosition = self.axisPosition,
                        labelOptions = options.label,
                        labelOffset = labelOptions.indentFromAxis,
                        labelsToDraw,
                        labelPoint,
                        label,
                        labels = [],
                        createText = options.isHorizontal ? renderer.createText : createTextForVerticalLabels,
                        currentLabelConst = options.isHorizontal ? axisPosition + labelOffset : axisPosition - labelOffset,
                        text;
                    if (!labelOptions.visible)
                        return;
                    labelsToDraw = prepareLabelsToDraw(self);
                    if (labelsToDraw.length === 0 || labelsToDraw.hideLabels)
                        return true;
                    for (i = 0; i < labelsToDraw.length; i++) {
                        labelPoint = labelsToDraw[i];
                        text = formatLabel(labelPoint.text, labelOptions);
                        if (utils.isDefined(text) && text !== '') {
                            label = createText.call(renderer, text, labelPoint.pos, currentLabelConst, self.textOptions);
                            labels.push(label);
                            label.append(group);
                            label.data({argument: labelPoint.text})
                        }
                    }
                    self.labels = labels
                };
            var getMultipleAxesSpacing = function() {
                    return this.options.multipleAxesSpacing || 0
                };
            var drawTitle = function drawTitle(self, group) {
                    var i,
                        options = self.options,
                        renderer = self.renderer,
                        axisPosition = self.axisPosition,
                        titleOptions = options.title,
                        margin = titleOptions.margin,
                        title,
                        attr = {
                            font: titleOptions.font,
                            opacity: titleOptions.opacity,
                            align: 'center',
                            'class': 'dx-chart-axis-title'
                        };
                    if (!titleOptions.text)
                        return;
                    if (self.options.isHorizontal)
                        if (self.options.position === 'bottom')
                            title = renderer.createText(titleOptions.text, self.translator.canvas.left + self.translator.width / 2, axisPosition, attr);
                        else
                            title = renderer.createText(titleOptions.text, self.translator.canvas.left + self.translator.width / 2, axisPosition, attr);
                    else if (self.options.position === 'left') {
                        attr.rotate = 270;
                        title = renderer.createText(titleOptions.text, axisPosition, self.translator.canvas.top + self.translator.height / 2, attr)
                    }
                    else {
                        attr.rotate = 90;
                        title = renderer.createText(titleOptions.text, axisPosition, self.translator.canvas.top + self.translator.height / 2, attr)
                    }
                    title.append(group);
                    self.title = title
                };
            var drawGrid = function drawGrid(self, group, borderOptions) {
                    var renderer = self.renderer,
                        options = self.options,
                        gridOptions = options.grid,
                        categories = options.categories,
                        translator = self.translator,
                        tickDelta = options.discreteAxisDivisionMode === 'crossLabels' ? 0 : 0.5,
                        positionsToDraw,
                        i,
                        attr = {
                            strokeWidth: gridOptions.width,
                            stroke: gridOptions.color,
                            strokeOpacity: gridOptions.opacity
                        },
                        currentTickConstant,
                        axisPosition = self.axisPosition,
                        positionFrom,
                        positionTo,
                        tick,
                        firstBorderLinePosition,
                        lastBorderLinePosition,
                        borderOptions = borderOptions || {visible: false};
                    if (!gridOptions.visible)
                        return;
                    positionsToDraw = prepareFullTicksToDraw(self);
                    if (self.options.isHorizontal) {
                        positionFrom = translator.translateY(CANVAS_POSITION_BOTTOM);
                        positionTo = translator.translateY(CANVAS_POSITION_TOP);
                        firstBorderLinePosition = borderOptions.visible && borderOptions.left ? translator.translateX(CANVAS_POSITION_LEFT) : undefined;
                        lastBorderLinePosition = borderOptions.visible && borderOptions.right ? translator.translateX(CANVAS_POSITION_RIGHT) : undefined;
                        for (i = 0; i < positionsToDraw.length; i++) {
                            tick = positionsToDraw[i];
                            if (mathAbs(tick.pos - firstBorderLinePosition) < MAX_GRID_BORDER_ADHENSION || mathAbs(tick.pos - lastBorderLinePosition) < MAX_GRID_BORDER_ADHENSION)
                                continue;
                            renderer.createLine(tick.pos, positionFrom, tick.pos, positionTo, attr).append(group)
                        }
                    }
                    else {
                        positionFrom = translator.translateX(CANVAS_POSITION_LEFT);
                        positionTo = translator.translateX(CANVAS_POSITION_RIGHT);
                        firstBorderLinePosition = borderOptions.visible && borderOptions.top ? translator.translateY(CANVAS_POSITION_TOP) : undefined;
                        lastBorderLinePosition = borderOptions.visible && borderOptions.bottom ? translator.translateY(CANVAS_POSITION_BOTTOM) : undefined;
                        for (i = 0; i < positionsToDraw.length; i++) {
                            tick = positionsToDraw[i];
                            if (mathAbs(tick.pos - firstBorderLinePosition) < MAX_GRID_BORDER_ADHENSION || mathAbs(tick.pos - lastBorderLinePosition) < MAX_GRID_BORDER_ADHENSION)
                                continue;
                            renderer.createLine(positionFrom, tick.pos, positionTo, tick.pos, attr).append(group)
                        }
                    }
                };
            var drawConstantLine = function drawConstantLine(self, group) {
                    var renderer = self.renderer,
                        options = self.options,
                        data = options.constantLines,
                        translator = self.translator,
                        isHorizontal = self.options.isHorizontal,
                        i,
                        lines = [],
                        labels = [],
                        positionFrom,
                        positionTo,
                        lineOptions,
                        range = translator.businessRange,
                        line;
                    var getPos = function(lineValue) {
                            var translate = isHorizontal ? function(val) {
                                    return translator.translateX(val)
                                } : function(val) {
                                    return translator.translateY(val)
                                },
                                parsedValue = self._validUnit(lineValue, 'Value of a constant line'),
                                value = translate(parsedValue),
                                isContinous = isHorizontal ? !!(range.minVisibleX || range.maxVisibleX) : !!(range.minVisibleY || range.maxVisibleY),
                                categories = (isHorizontal ? range.categoriesX : range.categoriesY) || [];
                            if (!isContinous && $.inArray(lineValue, categories) === -1 || !utils.isDefined(value))
                                return null;
                            return {
                                    value: value,
                                    parsedValue: parsedValue
                                }
                        };
                    positionFrom = isHorizontal ? translator.translateY(CANVAS_POSITION_BOTTOM) : translator.translateX(CANVAS_POSITION_LEFT);
                    positionTo = isHorizontal ? translator.translateY(CANVAS_POSITION_TOP) : translator.translateX(CANVAS_POSITION_RIGHT);
                    for (i = 0; i < data.length; i++) {
                        lineOptions = data[i];
                        if (lineOptions.value !== undefined) {
                            var pos = getPos(lineOptions.value),
                                value = pos && pos.value,
                                attr = {
                                    stroke: lineOptions.color,
                                    strokeWidth: lineOptions.width,
                                    dashStyle: lineOptions.dashStyle
                                };
                            if (!value && value !== 0) {
                                lines.push(null);
                                if (lineOptions.label && lineOptions.label.visible)
                                    labels.push(null);
                                continue
                            }
                            line = isHorizontal ? renderer.createLine(value, positionTo, value, positionFrom, attr) : renderer.createLine(positionFrom, value, positionTo, value, attr);
                            line.append(group);
                            lines.push(line);
                            if (lineOptions.label && lineOptions.label.visible)
                                labels.push(drawConstantLineLabels(self, pos.parsedValue, lineOptions.label, value, group));
                            else
                                labels.push(null)
                        }
                    }
                    self.constantLines = lines;
                    self.constantLineLabels = labels
                };
            var checkAlignmentConstantLineLabels = function(self, labelOptions) {
                    labelOptions.verticalAlignment = (labelOptions.verticalAlignment || '').toLowerCase();
                    labelOptions.horizontalAlignment = (labelOptions.horizontalAlignment || '').toLowerCase();
                    if (self.options.isHorizontal && labelOptions.position === 'outside') {
                        labelOptions.verticalAlignment = labelOptions.verticalAlignment === 'bottom' ? 'bottom' : 'top';
                        labelOptions.horizontalAlignment = 'center'
                    }
                    if (self.options.isHorizontal && labelOptions.position === 'inside') {
                        labelOptions.verticalAlignment = labelOptions.verticalAlignment === 'center' ? 'center' : labelOptions.verticalAlignment === 'bottom' ? 'bottom' : 'top';
                        labelOptions.horizontalAlignment = labelOptions.horizontalAlignment === 'left' ? 'left' : 'right'
                    }
                    if (!self.options.isHorizontal && labelOptions.position === 'outside') {
                        labelOptions.verticalAlignment = 'center';
                        labelOptions.horizontalAlignment = labelOptions.horizontalAlignment === 'left' ? 'left' : 'right'
                    }
                    if (!self.options.isHorizontal && labelOptions.position === 'inside') {
                        labelOptions.verticalAlignment = labelOptions.verticalAlignment === 'bottom' ? 'bottom' : 'top';
                        labelOptions.horizontalAlignment = labelOptions.horizontalAlignment === 'right' ? 'right' : labelOptions.horizontalAlignment === 'center' ? 'center' : 'left'
                    }
                };
            var drawConstantLineLabels = function drawConstantLineLabels(self, parsedValue, labelOptions, value, group) {
                    var renderer = self.renderer,
                        text = labelOptions.text,
                        canvas = self.translator.canvas,
                        attr = {
                            align: 'center',
                            font: $.extend({}, self.options.label.font, labelOptions.font)
                        },
                        label,
                        x,
                        y;
                    checkAlignmentConstantLineLabels(self, labelOptions);
                    text = utils.isDefined(text) ? text : formatLabel(parsedValue, self.options.label);
                    if (self.options.isHorizontal) {
                        x = value;
                        switch (labelOptions.horizontalAlignment) {
                            case'left':
                                attr.align = 'right';
                                break;
                            case'right':
                                attr.align = 'left';
                                break
                        }
                        switch (labelOptions.verticalAlignment) {
                            case'bottom':
                                y = canvas.height - canvas.bottom;
                                break;
                            case'center':
                                y = (canvas.height - canvas.top - canvas.bottom) / 2 + canvas.top;
                                break;
                            case'top':
                                y = canvas.top;
                                break
                        }
                    }
                    else {
                        y = value;
                        switch (labelOptions.horizontalAlignment) {
                            case'left':
                                x = canvas.left;
                                attr.align = labelOptions.position === 'inside' ? 'left' : 'right';
                                break;
                            case'center':
                                x = (canvas.width - canvas.left - canvas.right) / 2 + canvas.left;
                                attr.align = 'center';
                                break;
                            case'right':
                                x = canvas.width - canvas.right;
                                attr.align = labelOptions.position === 'inside' ? 'right' : 'left';
                                break
                        }
                    }
                    label = renderer.createText(text, x, y, attr);
                    label.append(group);
                    return label
                };
            var adjustConstantLineLabels = function(self) {
                    var options = self.options,
                        lines = self.constantLines,
                        label,
                        line,
                        lineBox,
                        canvas = self.translator.canvas,
                        linesOptions,
                        box,
                        x,
                        y,
                        i,
                        labelOptions,
                        padding = self.options.isHorizontal ? {
                            top: 0,
                            bottom: 0
                        } : {
                            left: 0,
                            right: 0
                        },
                        labels = self.constantLineLabels;
                    if (labels === undefined && lines === undefined)
                        return;
                    for (i = 0; i < labels.length; i++) {
                        x = y = 0;
                        linesOptions = options.constantLines[i];
                        labelOptions = linesOptions.label;
                        label = labels[i];
                        if (label !== null) {
                            line = lines[i];
                            box = label.getBBox();
                            lineBox = line.getBBox();
                            if (self.options.isHorizontal)
                                if (labelOptions.position === 'inside') {
                                    switch (labelOptions.horizontalAlignment) {
                                        case'left':
                                            x -= linesOptions.paddingLeftRight;
                                            break;
                                        default:
                                            x += linesOptions.paddingLeftRight;
                                            break
                                    }
                                    switch (labelOptions.verticalAlignment) {
                                        case'center':
                                            y += lineBox.y + lineBox.height / 2 - box.y - box.height / 2;
                                            break;
                                        case'bottom':
                                            y -= linesOptions.paddingTopBottom;
                                            break;
                                        default:
                                            y += linesOptions.paddingTopBottom + box.height;
                                            break
                                    }
                                }
                                else
                                    switch (labelOptions.verticalAlignment) {
                                        case'bottom':
                                            y += box.height + linesOptions.paddingTopBottom - (box.y + box.height - canvas.height + canvas.bottom);
                                            if (padding['bottom'] < box.height + linesOptions.paddingTopBottom)
                                                padding['bottom'] = box.height + linesOptions.paddingTopBottom;
                                            break;
                                        default:
                                            y -= linesOptions.paddingTopBottom;
                                            if (padding['top'] < linesOptions.paddingTopBottom + box.height)
                                                padding['top'] = linesOptions.paddingTopBottom + box.height;
                                            break
                                    }
                            else if (labelOptions.position === 'inside') {
                                switch (labelOptions.horizontalAlignment) {
                                    case'center':
                                        x += lineBox.x + lineBox.width / 2 - box.x - box.width / 2;
                                        break;
                                    case'right':
                                        x -= linesOptions.paddingLeftRight;
                                        break;
                                    default:
                                        x += linesOptions.paddingLeftRight;
                                        break
                                }
                                switch (labelOptions.verticalAlignment) {
                                    case'bottom':
                                        y += lineBox.y - box.y + linesOptions.paddingTopBottom;
                                        break;
                                    default:
                                        y -= linesOptions.paddingTopBottom;
                                        break
                                }
                            }
                            else {
                                y += lineBox.y + lineBox.height / 2 - box.y - box.height / 2;
                                switch (labelOptions.horizontalAlignment) {
                                    case'right':
                                        x += linesOptions.paddingLeftRight;
                                        if (padding['right'] < linesOptions.paddingLeftRight + box.width)
                                            padding['right'] = linesOptions.paddingLeftRight + box.width;
                                        break;
                                    default:
                                        x -= linesOptions.paddingLeftRight;
                                        if (padding['left'] < linesOptions.paddingLeftRight + box.width)
                                            padding['left'] = linesOptions.paddingLeftRight + box.width;
                                        break
                                }
                            }
                            label.move(x, y)
                        }
                    }
                    self.padding = padding
                };
            var drawStrip = function drawStrip(self, group) {
                    var renderer = self.renderer,
                        options = self.options,
                        stripData = options.strips,
                        translator = self.translator,
                        i,
                        stripLabels = [],
                        stripRects = [],
                        rect,
                        isHorizontal = self.options.isHorizontal,
                        stripOptions,
                        positionFrom,
                        positionTo,
                        stripPos;
                    if (options.stubData)
                        return;
                    var getPos = function(startV, endV, range) {
                            var isContinous = isHorizontal ? !!(range.minVisibleX || range.maxVisibleX) : !!(range.minVisibleY || range.maxVisibleY),
                                cateories = (isHorizontal ? range.categoriesX : range.categoriesY) || [],
                                translate = isHorizontal ? function(val) {
                                    return translator.translateX(val)
                                } : function(val) {
                                    return translator.translateY(val)
                                },
                                invert = isHorizontal ? !!range.invertX : range.invertY,
                                defaultPos = isHorizontal ? [CANVAS_POSITION_LEFT, CANVAS_POSITION_RIGHT] : [CANVAS_POSITION_BOTTOM, CANVAS_POSITION_TOP],
                                pos,
                                start = translate(self._validUnit(startV, 'Start value of a strip')),
                                end = translate(self._validUnit(endV, 'End value of a strip')),
                                min = isHorizontal ? range.minVisibleX : range.maxVisibleY,
                                max = isHorizontal ? range.maxVisibleX : range.maxVisibleY;
                            invert && defaultPos.reverse();
                            if (!isContinous && ($.inArray(startV, cateories) === -1 || $.inArray(endV, cateories) === -1))
                                return {
                                        stripFrom: 0,
                                        stripTo: 0
                                    };
                            if (!utils.isDefined(start) && isContinous)
                                start = startV < min ? translate(defaultPos[0]) : translate(defaultPos[1]);
                            if (!utils.isDefined(end) && isContinous)
                                end = endV < min ? translate(defaultPos[0]) : translate(defaultPos[1]);
                            return start < end ? {
                                    stripFrom: start,
                                    stripTo: end
                                } : {
                                    stripFrom: end,
                                    stripTo: start
                                }
                        };
                    positionFrom = isHorizontal ? translator.translateY(CANVAS_POSITION_BOTTOM) : translator.translateX(CANVAS_POSITION_LEFT);
                    positionTo = isHorizontal ? translator.translateY(CANVAS_POSITION_TOP) : translator.translateX(CANVAS_POSITION_RIGHT);
                    for (i = 0; i < stripData.length; i++) {
                        stripOptions = stripData[i];
                        if (stripOptions.startValue !== undefined && stripOptions.endValue !== undefined && stripOptions.color !== undefined) {
                            stripPos = getPos(stripOptions.startValue, stripOptions.endValue, translator.businessRange);
                            if (stripPos.stripTo - stripPos.stripFrom === 0 || !stripPos.stripTo && stripPos.stripTo !== 0 || !stripPos.stripFrom && stripPos.stripFrom !== 0) {
                                stripRects.push(null);
                                if (stripOptions.label && stripOptions.label.text)
                                    stripLabels.push(null);
                                continue
                            }
                            rect = isHorizontal ? renderer.createRect(stripPos.stripFrom, positionTo, stripPos.stripTo - stripPos.stripFrom, positionFrom - positionTo, 0, {fill: stripOptions.color}) : renderer.createRect(positionFrom, stripPos.stripFrom, positionTo - positionFrom, stripPos.stripTo - stripPos.stripFrom, 0, {fill: stripOptions.color});
                            rect.append(group);
                            stripRects.push(rect);
                            if (stripOptions.label && stripOptions.label.text)
                                stripLabels.push(drawStripLabel(self, stripOptions.label, stripPos.stripFrom, stripPos.stripTo, group));
                            else
                                stripLabels.push(null)
                        }
                    }
                    self.stripLabels = stripLabels;
                    self.stripRects = stripRects
                };
            var drawStripLabel = function drawStripLabel(self, labelOptions, stripFrom, stripTo, group) {
                    var renderer = self.renderer,
                        text = labelOptions.text,
                        canvas = self.translator.canvas,
                        attr = {
                            align: self.options.isHorizontal ? 'center' : 'left',
                            font: $.extend({}, self.options.label.font, labelOptions.font)
                        },
                        label,
                        x,
                        y;
                    if (self.options.isHorizontal) {
                        if (labelOptions.horizontalAlignment === 'center') {
                            x = stripFrom + (stripTo - stripFrom) / 2;
                            attr.align = 'center'
                        }
                        else if (labelOptions.horizontalAlignment === 'left') {
                            x = stripFrom;
                            attr.align = 'left'
                        }
                        else if (labelOptions.horizontalAlignment === 'right') {
                            x = stripTo;
                            attr.align = 'right'
                        }
                        if (labelOptions.verticalAlignment === 'top')
                            y = canvas.top;
                        else if (labelOptions.verticalAlignment === 'center')
                            y = (canvas.height - canvas.top - canvas.bottom) / 2 + canvas.top;
                        else if (labelOptions.verticalAlignment === 'bottom')
                            y = canvas.height - canvas.bottom
                    }
                    else {
                        if (labelOptions.horizontalAlignment === 'center') {
                            x = (canvas.width - canvas.left - canvas.right) / 2 + canvas.left;
                            attr.align = 'center'
                        }
                        else if (labelOptions.horizontalAlignment === 'left') {
                            x = canvas.left;
                            attr.align = 'left'
                        }
                        else if (labelOptions.horizontalAlignment === 'right') {
                            x = canvas.width - canvas.right;
                            attr.align = 'right'
                        }
                        if (labelOptions.verticalAlignment === 'top')
                            y = stripFrom;
                        else if (labelOptions.verticalAlignment === 'center')
                            y = stripTo + (stripFrom - stripTo) / 2;
                        else if (labelOptions.verticalAlignment === 'bottom')
                            y = stripTo
                    }
                    label = renderer.createText(text, x, y, attr);
                    label.append(group);
                    return label
                };
            var initAxisPositions = function(self) {
                    if (self.options.isHorizontal)
                        self.axisPosition = getYAxisPosition(self);
                    else
                        self.axisPosition = getXAxisPosition(self)
                };
            var adjustLabels = function(self) {
                    var options = self.options,
                        labels = self.labels,
                        labelOptions = options.label,
                        label,
                        labelHeight,
                        isNeedLabelAdjustment,
                        staggeringSpacing,
                        i,
                        xt,
                        shift = self.padding && self.padding[options.position] || 0,
                        boxAxis = self._axisElementsGroup && self._axisElementsGroup.getBBox() || {},
                        box;
                    if (!options.label.visible || !labels || !labels.length)
                        return;
                    for (i = 0; i < labels.length; i++) {
                        label = labels[i];
                        box = label.getBBox();
                        if (options.isHorizontal && options.position === 'bottom')
                            label.applySettings({y: 2 * label.settings.y - box.y + shift});
                        else if (!options.isHorizontal) {
                            if (options.position === 'left')
                                if (self.textOptions.align === 'right')
                                    xt = box.x + box.width - shift;
                                else if (self.textOptions.align === 'center')
                                    xt = box.x + box.width / 2 - shift - (boxAxis.width / 2 || 0);
                                else
                                    xt = box.x - shift - (boxAxis.width || 0);
                            else if (self.textOptions.align === 'center')
                                xt = box.x + box.width / 2 + (boxAxis.width / 2 || 0) + shift;
                            else if (self.textOptions.align === 'right')
                                xt = box.x + box.width + (boxAxis.width || 0) + shift;
                            else
                                xt = box.x + shift;
                            label.applySettings({
                                x: xt,
                                y: label.settings.y + ~~(label.settings.y - box.y - box.height / 2)
                            })
                        }
                        else if (options.isHorizontal && options.position === 'top')
                            label.applySettings({y: 2 * label.settings.y - box.y - box.height - shift})
                    }
                    isNeedLabelAdjustment = options.isHorizontal && self.overlappingBehavior && self.overlappingBehavior.mode === 'stagger';
                    self._testIsNeedLabelAdjustment = isNeedLabelAdjustment;
                    if (isNeedLabelAdjustment) {
                        labelHeight = 0;
                        for (i = 0; i < labels.length; i = i + 2) {
                            label = labels[i];
                            box = label.getBBox();
                            if (box.height > labelHeight)
                                labelHeight = box.height
                        }
                        staggeringSpacing = self.overlappingBehavior.staggeringSpacing;
                        self._testStaggeringSpacing = staggeringSpacing;
                        labelHeight = Math.round(labelHeight) + staggeringSpacing;
                        for (i = 1; i < labels.length; i = i + 2) {
                            label = labels[i];
                            if (options.position === 'bottom')
                                label.move(0, labelHeight);
                            else if (options.position === 'top')
                                label.move(0, -labelHeight)
                        }
                        for (i = 0; i < labels.length; i++)
                            labels[i].rotate(0)
                    }
                };
            var adjustStripLabels = function(self) {
                    var options = self.options,
                        labelOptions,
                        labels = self.stripLabels,
                        rects = self.stripRects,
                        rect,
                        label,
                        i,
                        box,
                        rectBox,
                        stripOptions,
                        x,
                        y;
                    if (labels === undefined && rects === undefined)
                        return;
                    for (i = 0; i < labels.length; i++) {
                        x = y = 0;
                        stripOptions = options.strips[i];
                        labelOptions = stripOptions.label;
                        label = labels[i];
                        if (label !== null) {
                            rect = rects[i];
                            box = label.getBBox();
                            rectBox = rect.getBBox();
                            if (labelOptions.horizontalAlignment === 'left')
                                x += stripOptions.paddingLeftRight;
                            else if (labelOptions.horizontalAlignment === 'right')
                                x -= stripOptions.paddingLeftRight;
                            if (labelOptions.verticalAlignment === 'top')
                                y += rectBox.y - box.y + stripOptions.paddingTopBottom;
                            else if (labelOptions.verticalAlignment === 'center')
                                y += rectBox.y + rectBox.height / 2 - box.y - box.height / 2;
                            else if (labelOptions.verticalAlignment === 'bottom')
                                y -= stripOptions.paddingTopBottom;
                            label.move(x, y)
                        }
                    }
                };
            var adjustTitle = function(self, group) {
                    var options = self.options,
                        axisPosition = self.axisPosition,
                        boxGroup,
                        boxTitle,
                        title = self.title;
                    if (!title)
                        return;
                    boxTitle = title.getBBox();
                    boxGroup = group.getBBox();
                    if (self.options.isHorizontal)
                        if (self.options.position === 'bottom')
                            title.move(0, boxGroup.y + boxGroup.height - boxTitle.y + options.title.margin);
                        else
                            title.move(0, boxGroup.y - boxTitle.y - boxTitle.height - options.title.margin);
                    else if (self.options.position === 'left')
                        title.move(boxGroup.x - boxTitle.x - boxTitle.width - options.title.margin, 0);
                    else
                        title.move(boxGroup.x + boxGroup.width - boxTitle.x + options.title.margin, 0)
                };
            var draw = function(externalOptions) {
                    var _this = this,
                        cssClass = _this.options.isHorizontal ? 'dxc-h-axis' : 'dxc-v-axis',
                        stripClass = _this.options.isHorizontal ? 'dxc-h-strips' : 'dxc-v-strips',
                        constantLineClass = _this.options.isHorizontal ? 'dxc-h-constant-lines' : 'dxc-v-constant-lines',
                        axisClipRectID = _this.clipRectID && _this.options.placeholderSize ? _this.clipRectID : undefined;
                    externalOptions = externalOptions || {};
                    var debug = DX.utils.debug;
                    debug.assertParam(this.translator, 'translator was not set before Draw call');
                    if (_this._axisGroup) {
                        _this._axisGroup.detach();
                        _this._axisStripGroup.detach();
                        _this._axisConstantLineGroup.detach();
                        _this._axisGridGroup.clear();
                        _this._axisElementsGroup.clear();
                        _this._axisLineGroup.clear();
                        _this._axisStripGroup.clear();
                        _this._axisConstantLineGroup.clear()
                    }
                    else {
                        _this._axisGroup = _this.renderer.createGroup({
                            'class': cssClass,
                            clipId: axisClipRectID
                        });
                        _this._axisStripGroup = _this.renderer.createGroup({'class': stripClass});
                        _this._axisGridGroup = _this.renderer.createGroup({'class': 'dxc-grid'}).append(_this._axisGroup);
                        _this._axisElementsGroup = _this.renderer.createGroup({'class': 'dxc-elements'}).append(_this._axisGroup);
                        _this._axisLineGroup = _this.renderer.createGroup({'class': 'dxc-line'}).append(_this._axisGroup);
                        _this._axisConstantLineGroup = _this.renderer.createGroup({'class': constantLineClass})
                    }
                    initAxisPositions(_this);
                    if (!_this._virtual) {
                        drawAxis(_this, _this._axisLineGroup);
                        drawTicks(_this, _this._axisLineGroup);
                        drawLabels(_this, _this._axisElementsGroup);
                        if (_this.options.title.text)
                            drawTitle(_this, _this._axisElementsGroup)
                    }
                    if (_this.options.strips)
                        drawStrip(_this, _this._axisStripGroup);
                    if (_this.options.constantLines)
                        drawConstantLine(_this, _this._axisConstantLineGroup);
                    drawGrid(_this, _this._axisGridGroup, externalOptions.borderOptions);
                    _this._axisStripGroup.append(_this.stripsGroup);
                    _this._axisConstantLineGroup.append(_this.constantLinesGroup);
                    _this._axisGroup.append(_this.axesContainerGroup);
                    adjustConstantLineLabels(_this);
                    adjustLabels(_this);
                    adjustStripLabels(_this);
                    adjustTitle(_this, _this._axisElementsGroup)
                };
            var getBoundingRect = function() {
                    var box = this._axisElementsGroup.getBBox(),
                        lineBox = this._axisLineGroup.getBBox(),
                        placeholderSize = this.options.placeholderSize,
                        start,
                        isHorizontal = this.options.isHorizontal,
                        coord = isHorizontal && 'y' || 'x',
                        side = isHorizontal && 'height' || 'width',
                        positionCondition = this.options.position === (isHorizontal && 'bottom' || 'right');
                    if (!(box.x || box.y || box.width || box.height))
                        return box;
                    start = lineBox[coord] || this.axisPosition;
                    if (positionCondition) {
                        box[side] = placeholderSize || box[side] - (start - box[coord]);
                        box[coord] = start
                    }
                    else
                        box[side] = placeholderSize || lineBox[side] + start - box[coord];
                    return box
                };
            var shift = function(x, y) {
                    var settings = {};
                    if (x)
                        settings.translateX = x;
                    if (y)
                        settings.translateY = y;
                    this._axisGroup.applySettings(settings)
                };
            var applyClipRect = function(clipId) {
                    this._axisStripGroup.applySettings({clipId: clipId});
                    this._axisConstantLineGroup.applySettings({clipId: clipId})
                };
            var validate = function(isArgumentAxis, incidentOccured) {
                    var options = this.options,
                        parseUtils = new ParseUtils,
                        type = isArgumentAxis ? this.options.argumentType : this.options.valueType,
                        parser = type ? parseUtils.getParser(type, 'axis') : function(unit) {
                            return unit
                        };
                    this.parser = parser;
                    this.incidentOccured = incidentOccured;
                    this.options.axisType = type;
                    this._errorMessages = {
                        unsupportedFieldMessage: function(field) {
                            return field + " contains data of unsupported axis type."
                        },
                        numericParsingMessage: function(field, count) {
                            return field + " cannot be parsed to the axis numeric type."
                        },
                        dateParsingMessage: function(field, count) {
                            return field + "  cannot be parsed to the axis date type."
                        }
                    };
                    if (options.min)
                        options.min = this._validUnit(options.min, "Value of the 'min' option");
                    if (options.max)
                        options.max = this._validUnit(options.max, "Value of the 'max' option");
                    if (options.range.min)
                        options.range.min = this._validUnit(options.range.min);
                    if (options.range.max)
                        options.range.max = this._validUnit(options.range.max)
                };
            var _validUnit = function(unit, field) {
                    var type = this.options.axisType;
                    unit = this.parser(unit);
                    if (unit === undefined && field) {
                        type === 'datetime' && this.incidentOccured(this._errorMessages.dateParsingMessage(field));
                        type === 'numeric' && this.incidentOccured(this._errorMessages.numericParsingMessage(field));
                        type !== 'numeric' && type !== 'datetime' && this.incidentOccured(this._errorMessages.unsupportedFieldMessage(field))
                    }
                    return unit
                };
            var getRangeData = function() {
                    var options = this.options,
                        range = {};
                    var addValueMarginToRange = function(prefix, dim) {
                            if (options['valueMarginsEnabled']) {
                                if (utils.isDefined(options[prefix])) {
                                    range[prefix + dim] = options[prefix];
                                    range[prefix + dim + 'Priority'] = AXIS_VALUE_MARGIN_PRIORITY
                                }
                            }
                            else {
                                range[prefix + dim] = 0;
                                range[prefix + dim + 'Priority'] = AXIS_VALUE_MARGIN_PRIORITY
                            }
                        };
                    if (options.isHorizontal) {
                        range.minX = options.range.min;
                        range.maxX = options.range.max;
                        range.minVisibleX = options.range.min;
                        range.maxVisibleX = options.range.max;
                        addValueMarginToRange('minValueMargin', 'X');
                        addValueMarginToRange('maxValueMargin', 'X');
                        range.invertX = options.inverted;
                        range.stickX = !options.valueMarginsEnabled;
                        range.categoriesX = options.range.categories;
                        range.axisTypeX = options.type;
                        if (range.axisTypeX === 'logarithmic')
                            range.baseX = options.logarithmBase
                    }
                    else {
                        range.minY = options.range.min;
                        range.maxY = options.range.max;
                        range.minVisibleY = options.range.min;
                        range.maxVisibleY = options.range.max;
                        range.invertY = options.inverted || options.type === 'discrete' && options.oppositeDirectionYAxis;
                        range.stickY = !options.valueMarginsEnabled;
                        addValueMarginToRange('minValueMargin', 'Y');
                        addValueMarginToRange('maxValueMargin', 'Y');
                        range.categoriesY = options.range.categories;
                        range.axisTypeY = options.type;
                        if (range.axisTypeY === 'logarithmic')
                            range.baseY = options.logarithmBase
                    }
                    return range
                };
            var on = function(events, data, handler) {
                    this._$axis && this._$axis.on(events, data, handler);
                    return this
                };
            var off = function(events) {
                    this._$axis && this._$axis.off(events);
                    return this
                };
            var prototypeObject = {
                    _getOptimalRotationAngle: _getOptimalRotationAngle,
                    _applyOptimalOverlappingBehavior: _applyOptimalOverlappingBehavior,
                    ctor: ctor,
                    dispose: dispose,
                    init: init,
                    resetTicks: resetTicks,
                    setTranslator: setTranslator,
                    getTickValues: getTickValues,
                    setTickValues: setTickValues,
                    getRangeData: getRangeData,
                    getMultipleAxesSpacing: getMultipleAxesSpacing,
                    setRange: setRange,
                    setPercentLabelFormat: setPercentLabelFormat,
                    resetAutoLabelFormat: resetAutoLabelFormat,
                    draw: draw,
                    getBoundingRect: getBoundingRect,
                    shift: shift,
                    on: on,
                    off: off,
                    validate: validate,
                    applyClipRect: applyClipRect,
                    _validUnit: _validUnit
                };
            prototypeObject.getTicksOptions = getTicksOptions;
            prototypeObject.drawAxis = drawAxis;
            prototypeObject.drawTicks = drawTicks;
            prototypeObject.drawGrid = drawGrid;
            prototypeObject.drawStrip = drawStrip;
            prototypeObject.drawLabels = drawLabels;
            prototypeObject.adjustLabels = adjustLabels;
            prototypeObject.adjustStripLabels = adjustStripLabels;
            prototypeObject.drawTitle = drawTitle;
            prototypeObject.adjustTitle = adjustTitle;
            prototypeObject.initAxisPositions = initAxisPositions;
            prototypeObject.drawConstantLine = drawConstantLine;
            prototypeObject.drawConstantLineLabels = drawConstantLineLabels;
            prototypeObject.adjustConstantLineLabels = adjustConstantLineLabels;
            prototypeObject.checkAlignmentConstantLineLabels = checkAlignmentConstantLineLabels;
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz-charts, file baseChart.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            charts = DX.viz.charts,
            utils = DX.utils,
            dataUtils = DX.data.utils,
            REDRAW_DELAY = 100,
            resizeRedrawOptions = {animate: false},
            ACTIONS_BY_PRIORITY = ['processAxesOption', 'reinit', '_reinitDataSource', '_handleDataSourceChanged', 'force_render'];
        charts.BaseChart = ui.Component.inherit({
            _defaultOptions: function() {
                return {
                        done: $.noop,
                        drawn: $.noop,
                        redrawOnResize: true,
                        incidentOccured: $.noop,
                        margin: {
                            left: 0,
                            top: 0,
                            right: 0,
                            bottom: 0
                        },
                        size: {
                            width: undefined,
                            height: undefined
                        },
                        title: {text: null},
                        legend: {hoverMode: 'includePoints'},
                        animation: {
                            enabled: true,
                            duration: 1000,
                            easing: 'easeOutCubic',
                            maxPointCountSupported: 300,
                            asyncSeriesRendering: true,
                            asyncTrackersRendering: true,
                            trackerRenderingDelay: 1200
                        },
                        seriesSelectionMode: 'single',
                        pointSelectionMode: 'single',
                        seriesClick: null,
                        pointClick: null,
                        legendClick: null,
                        argumentAxisClick: null,
                        seriesHover: null,
                        pointHover: null,
                        seriesSelected: null,
                        pointSelected: null,
                        seriesSelectionChanged: null,
                        pointSelectionChanged: null,
                        seriesHoverChanged: null,
                        pointHoverChanged: null
                    }
            },
            _init: function() {
                var _this = this;
                _this._saveUserCanvas();
                _this._initRenderer();
                _this._createHtmlStructure();
                _this._needHandleRenderComplete = true;
                _this.layoutManager = charts.factory.createChartLayoutManager();
                _this._reinit();
                _this._element().css({webkitUserSelect: 'none'});
                _this._element().on('contextmenu', function(event) {
                    _this.eventType = 'contextmenu';
                    if (ui.events.isTouchEvent(event) || ui.events.isPointerEvent(event))
                        event.preventDefault()
                });
                _this._element().on('MSHoldVisual', function(event) {
                    _this.eventType = 'MSHoldVisual';
                    event.preventDefault()
                })
            },
            _reinit: function() {
                var _this = this;
                _this.layoutManager.update(_this);
                if (_this.option('redrawOnResize') && window) {
                    if (!_this._resizeHandlerCallback) {
                        _this._resizeHandlerCallback = _this._resizeHandler();
                        utils.windowResizeCallbacks.add(_this._resizeHandlerCallback)
                    }
                }
                else {
                    utils.windowResizeCallbacks.remove(_this._resizeHandlerCallback);
                    delete _this._resizeHandlerCallback
                }
                if (!$.isFunction(_this.option('incidentOccured'))) {
                    utils.debug.assert(false, 'Function should be passed as "incidentOccured" callback');
                    _this.option('incidentOccured', $.noop)
                }
                _this._createTracker();
                _this._reinitDataSource()
            },
            _createHtmlStructure: function() {
                var _this = this,
                    renderer = _this.renderer;
                _this._panesBackgroundGroup = renderer.createGroup({'class': 'dxc-background'});
                _this._titleGroup = renderer.createGroup({'class': 'dxc-title'});
                _this._legendGroup = renderer.createGroup({'class': 'dxc-legend'});
                _this._stripsGroup = renderer.createGroup({'class': 'dxc-strips-group'});
                _this._constantLinesGroup = renderer.createGroup({'class': 'dxc-constant-lines-group'});
                _this._axesGroup = renderer.createGroup({'class': 'dxc-axes-group'});
                _this._panesBorderGroup = renderer.createGroup({'class': 'dxc-border'});
                _this._seriesGroup = renderer.createGroup({'class': 'dxc-series-group'});
                _this._labelsGroup = renderer.createGroup({'class': 'dxc-labels-group'});
                _this._tooltipGroup = renderer.createGroup({'class': 'dxc-tooltip'});
                _this._trackerGroup = renderer.createGroup({
                    'class': 'dxc-trackers',
                    opacity: 0.0001
                });
                _this._crosshairTrackerGroup = renderer.createGroup({
                    'class': 'dxc-crosshair-trackers',
                    stroke: 'none',
                    fill: 'grey'
                }).append(_this._trackerGroup);
                _this._seriesTrackerGroup = renderer.createGroup({'class': 'dxc-series-trackers'}).append(_this._trackerGroup);
                _this._markerTrackerGroup = renderer.createGroup({
                    'class': 'dxc-markers-trackers',
                    stroke: 'none',
                    fill: 'grey'
                }).append(_this._trackerGroup);
                _this._legendTrackerGroup = renderer.createGroup({
                    'class': 'dxc-legend-trackers',
                    stroke: 'none',
                    fill: 'grey'
                }).append(_this._trackerGroup);
                _this._crossHairCursorGroup = renderer.createGroup({'class': 'dxc-crosshair-cursor'})
            },
            _cleanHtmlStructure: function() {
                var _this = this;
                _this._panesBackgroundGroup && _this._panesBackgroundGroup.clear();
                _this._titleGroup && _this._titleGroup.clear();
                _this._legendGroup && (_this._legendGroup.detach(), _this._legendGroup.clear());
                _this._stripsGroup && (_this._stripsGroup.detach(), _this._stripsGroup.clear());
                _this._constantLinesGroup && (_this._constantLinesGroup.detach(), _this._constantLinesGroup.clear());
                _this._axesGroup && (_this._axesGroup.detach(), _this._axesGroup.clear());
                _this._seriesGroup && (_this._seriesGroup.detach(), _this._seriesGroup.clear());
                _this._labelsGroup && (_this._labelsGroup.detach(), _this._labelsGroup.clear());
                _this._trackerGroup && (_this._trackerGroup.detach(), _this._seriesTrackerGroup.clear(), _this._markerTrackerGroup.clear(), _this._legendTrackerGroup.clear(), _this._crosshairTrackerGroup.clear());
                _this._panesBorderGroup && _this._panesBorderGroup.clear();
                _this._tooltipGroup && _this._tooltipGroup.clear();
                _this._crossHairCursorGroup && (_this._crossHairCursorGroup.clear(), _this._crossHairCursorGroup.detach())
            },
            _disposeObjectsInArray: function(propName) {
                $.each(this[propName] || [], function(_, item) {
                    item && item.dispose()
                });
                this[propName] = null
            },
            _dispose: function() {
                var _this = this,
                    disposeObject = function(propName) {
                        _this[propName] && _this[propName].dispose(),
                        _this[propName] = null
                    },
                    detachGroup = function(groupName) {
                        _this[groupName] && _this[groupName].detach()
                    },
                    disposeObjectsInArray = this._disposeObjectsInArray;
                clearTimeout(_this.delayedRedraw);
                if (_this._resizeHandlerCallback) {
                    _this._resizeHandlerCallback.stop();
                    utils.windowResizeCallbacks.remove(_this._resizeHandlerCallback);
                    _this._resizeHandlerCallback = null
                }
                _this.callBase();
                disposeObjectsInArray.call(_this, "businessRanges");
                disposeObjectsInArray.call(_this, "translators");
                disposeObjectsInArray.call(_this, "series");
                disposeObject("layoutManager");
                disposeObject("themeManager");
                disposeObject("renderer");
                disposeObject("tracker");
                disposeObject("tooltip");
                disposeObject("chartTitle");
                _this.paneAxis = null;
                _this._userOptions = null;
                _this.dirtyCanvas = null;
                _this.canvas = null;
                detachGroup("_legendGroup");
                detachGroup("_stripsGroup");
                detachGroup("_constantLinesGroup");
                detachGroup("_axesGroup");
                detachGroup("_seriesGroup");
                detachGroup("_labelsGroup");
                detachGroup("_trackerGroup");
                detachGroup("_crossHairCursorGroup");
                disposeObject("canvasClipRect");
                disposeObject("_panesBackgroundGroup");
                disposeObject("_titleGroup");
                disposeObject("_legendGroup");
                disposeObject("_stripsGroup");
                disposeObject("_constantLinesGroup");
                disposeObject("_axesGroup");
                disposeObject("_panesBorderGroup");
                disposeObject("_seriesGroup");
                disposeObject("_labelsGroup");
                disposeObject("_tooltipGroup");
                disposeObject("_crossHairCursorGroup");
                disposeObject("_seriesTrackerGroup");
                disposeObject("_markerTrackerGroup");
                disposeObject("_legendTrackerGroup");
                disposeObject("_crosshairTrackerGroup");
                disposeObject("_trackerGroup")
            },
            _clean: function _clean() {
                this.renderer.stopAllAnimations();
                this._cleanHtmlStructure();
                this.callBase();
                this._saveDirtyCanvas()
            },
            _initRenderer: function _initRenderer() {
                if (this.renderer)
                    return;
                var _this = this,
                    animationOptions = _this.option('animation');
                animationOptions = animationOptions === true ? _this._defaultOptions().animation : animationOptions;
                _this.renderer = charts.factory.createRenderer({
                    animation: animationOptions,
                    cssClass: 'dxc dxc-chart'
                })
            },
            _initSeries: function() {
                this.series = this.series || this._populateSeries()
            },
            _reinitDataSource: function() {
                this._refreshDataSource()
            },
            _initOptions: function(options) {
                this._optionsInitializing = true;
                var _this = this,
                    changedTitle = _this._processTitleOption(options.title, _this.option('title'));
                if (changedTitle)
                    options.title = changedTitle;
                _this._userOptions = options;
                if (!options.incidentOccured)
                    options.incidentOccured = utils.logger.warn;
                _this._processAxesOption(options);
                _this._createThemeManager(options);
                _this.option(_this.themeManager.applyChartTheme(options));
                delete _this._userOptions.userCommonAxisSettings
            },
            _processTitleOption: function(title, oldTitle) {
                if (utils.isString(title)) {
                    var text = title;
                    title = oldTitle;
                    title.text = text;
                    return title
                }
            },
            _processAxesOption: function(options) {
                var argumentAxesOptions = $.isArray(options.argumentAxis) ? options.argumentAxis : [options.argumentAxis],
                    valueAxesOptions = $.isArray(options.valueAxis) ? options.valueAxis : [options.valueAxis],
                    incidentOccured = options.incidentOccured,
                    checkOptions = function(axesOptions) {
                        var axisOptions,
                            text,
                            i = 0;
                        for (i = 0; i < axesOptions.length; i++) {
                            axisOptions = axesOptions[i];
                            if (!axisOptions)
                                continue;
                            if (axisOptions.title)
                                if (utils.isString(axisOptions.title)) {
                                    text = axisOptions.title;
                                    axisOptions.title = {};
                                    axisOptions.title.text = text
                                }
                            if (axisOptions.type === 'logarithmic' && axisOptions.logarithmBase <= 0 || axisOptions.logarithmBase && !$.isNumeric(axisOptions.logarithmBase)) {
                                axisOptions.logarithmBase = undefined;
                                incidentOccured && incidentOccured.call && incidentOccured('Value of the "logarithmBase" option is not valid. So a default value is set instead.')
                            }
                            if (axisOptions.label) {
                                if (axisOptions.label.alignment)
                                    axisOptions.label['userAlignment'] = true;
                                if (!axisOptions.label.overlappingBehavior) {
                                    if (axisOptions.label.staggered)
                                        axisOptions.label.overlappingBehavior = {
                                            mode: 'stagger',
                                            staggeringSpacing: axisOptions.label.staggeringSpacing
                                        };
                                    if (axisOptions.label.rotationAngle)
                                        axisOptions.label.overlappingBehavior = {
                                            mode: 'rotate',
                                            rotationAngle: axisOptions.label.rotationAngle
                                        }
                                }
                                if (utils.isString(axisOptions.label.overlappingBehavior))
                                    axisOptions.label.overlappingBehavior = {mode: axisOptions.label.overlappingBehavior};
                                if (!axisOptions.label.overlappingBehavior || !axisOptions.label.overlappingBehavior.mode)
                                    axisOptions.label.overlappingBehavior = axisOptions.label.overlappingBehavior || {}
                            }
                        }
                    };
                options.userCommonAxisSettings = this._userOptions.commonAxisSettings;
                checkOptions([options.commonAxisSettings]);
                checkOptions(argumentAxesOptions);
                checkOptions(valueAxesOptions)
            },
            _saveUserCanvas: function() {
                var canvas = this.option('size');
                if (canvas.width !== undefined)
                    canvas.userWidth = canvas.width;
                if (canvas.height !== undefined)
                    canvas.userHeight = canvas.height
            },
            _saveDirtyCanvas: function() {
                this.dirtyCanvas = this._calculateCanvas()
            },
            _resizeHandler: function() {
                var _this = this;
                return utils.createResizeHandler(function() {
                        _this._render(resizeRedrawOptions)
                    })
            },
            _createThemeManager: function(options) {
                options = options || {};
                var _this = this;
                _this.themeManager && _this.themeManager.dispose();
                _this.themeManager = charts.factory.createThemeManager({
                    theme: options.theme,
                    palette: options.palette
                })
            },
            _calculateCanvas: function() {
                var canvas = this.option('size'),
                    container = this._element();
                if (!utils.isDefined(canvas.userWidth)) {
                    canvas.width = container.width();
                    if (!canvas.width)
                        canvas.width = 400
                }
                if (!utils.isDefined(canvas.userHeight)) {
                    canvas.height = container.height();
                    if (!canvas.height)
                        canvas.height = 400
                }
                return $.extend({}, canvas, this.option('margin'))
            },
            _createTracker: function() {
                var _this = this,
                    rotated = _this.option('rotated'),
                    tooltipOptions = _this.option('tooltip') || {};
                if (_this.tracker)
                    _this.tracker.dispose();
                _this.tracker = charts.factory.createTracker({
                    series: _this.series,
                    valueAxis: rotated ? _this.horizontalAxes : _this.verticalAxes,
                    argumentAxis: rotated ? _this.verticalAxes : _this.horizontalAxes,
                    seriesSelectionMode: _this.option('seriesSelectionMode'),
                    pointSelectionMode: _this.option('pointSelectionMode'),
                    tooltipShown: _this.option('tooltipShown'),
                    tooltipHidden: _this.option('tooltipHidden'),
                    markerTrackerGroup: _this._markerTrackerGroup,
                    crossHairOptions: _this._crossHairOptions,
                    seriesTrackerGroup: _this._seriesTrackerGroup,
                    legendGroup: _this._legendTrackerGroup,
                    seriesGroup: _this._seriesGroup,
                    tooltipEnabled: tooltipOptions.enabled,
                    renderer: _this.renderer,
                    events: {
                        seriesClick: _this.option('seriesClick'),
                        pointClick: _this.option('pointClick'),
                        argumentAxisClick: _this.option('argumentAxisClick'),
                        seriesHover: _this.option('seriesHover'),
                        seriesSelected: _this.option('seriesSelected'),
                        pointHover: _this.option('pointHover'),
                        pointSelected: _this.option('pointSelected'),
                        legendClick: _this.option('legendClick'),
                        seriesSelectionChanged: _this.option('seriesSelectionChanged'),
                        pointSelectionChanged: _this.option('pointSelectionChanged'),
                        seriesHoverChanged: _this.option('seriesHoverChanged'),
                        pointHoverChanged: _this.option('pointHoverChanged')
                    }
                })
            },
            _updateTracker: function() {
                var _this = this,
                    rotated = _this.option('rotated');
                if (!_this.tracker)
                    _this._createTracker();
                else
                    _this.tracker._reinit({
                        series: _this.series,
                        valueAxis: rotated ? _this.horizontalAxes : _this.verticalAxes,
                        argumentAxis: rotated ? _this.verticalAxes : _this.horizontalAxes
                    })
            },
            _render: function(drawOptions) {
                this._optionsInitializing = false;
                var _this = this,
                    renderer = _this.renderer,
                    translators = _this.translators,
                    updatedCanvas = _this.canvas,
                    container = this._element(),
                    currentDirtyCanvas = _this._calculateCanvas(),
                    oldDirtyCanvas = _this.dirtyCanvas;
                drawOptions = drawOptions || {recreateCanvas: true};
                drawOptions.recreateCanvas = drawOptions.recreateCanvas || !renderer.isInitialized();
                if (!drawOptions.force && oldDirtyCanvas && oldDirtyCanvas.width === currentDirtyCanvas.width && oldDirtyCanvas.height === currentDirtyCanvas.height && !_this.hiddenContainer) {
                    _this.stopRedraw = true;
                    return
                }
                clearTimeout(_this.delayedRedraw);
                if (drawOptions.recreateCanvas)
                    updatedCanvas = _this._calculateCanvas();
                if (updatedCanvas.width && updatedCanvas.height && container.is(':visible'))
                    _this.hiddenContainer = false;
                else {
                    _this.option('incidentOccured')('Chart cannot be drawn because its container is not visible');
                    _this.hiddenContainer = true;
                    _this.stopRedraw = true;
                    renderer.killContainer();
                    return
                }
                if (drawOptions.recreateCanvas) {
                    _this.canvas = updatedCanvas;
                    renderer.recreateCanvas(_this.canvas.width, _this.canvas.height);
                    renderer.draw(_this._element()[0]);
                    _this._createCanvasClipRect();
                    if (translators)
                        translators.length = 0
                }
                _this.layoutManager.update(_this);
                _this._cleanGroups(drawOptions);
                _this._saveDirtyCanvas()
            },
            _cleanGroups: function(drawOptions) {
                var _this = this;
                _this._stripsGroup.detach();
                _this._constantLinesGroup.detach();
                _this._axesGroup.detach();
                _this._seriesGroup.detach();
                _this._labelsGroup.detach();
                _this._trackerGroup.detach();
                _this._tooltipGroup.detach();
                _this._crossHairCursorGroup.detach();
                if (!drawOptions || drawOptions.drawLegend) {
                    _this._legendGroup.detach();
                    _this._legendGroup.clear()
                }
                _this._stripsGroup.clear();
                _this._constantLinesGroup.clear();
                _this._axesGroup.clear();
                _this._seriesGroup.clear();
                _this._labelsGroup.clear();
                _this._tooltipGroup.clear();
                _this._crossHairCursorGroup.clear();
                _this._seriesTrackerGroup.clear();
                _this._markerTrackerGroup.clear();
                _this._legendTrackerGroup.clear();
                _this._crosshairTrackerGroup.clear()
            },
            _drawTitle: function() {
                var _this = this;
                if (_this.chartTitle)
                    _this.chartTitle.update(_this.canvas, _this.option('title'));
                else
                    _this.chartTitle = charts.factory.createTitle(_this.renderer, _this.canvas, _this.option('title'), _this._titleGroup);
                _this.chartTitle.render()
            },
            _createTooltip: function() {
                var _this = this,
                    tooltipOptions = $.extend(true, {
                        renderer: _this.renderer,
                        canvasWidth: _this.canvas.width,
                        canvasHeight: _this.canvas.height
                    }, _this.option('tooltip') || {}),
                    tooltipCoords,
                    point = this.tracker.pointAtShownTooltip;
                if (!$.isFunction(tooltipOptions.customizeText) && utils.isDefined(tooltipOptions.customizeText)) {
                    _this.option('incidentOccured').call(null, 'customizeText cannot be applied because it is not a function');
                    tooltipOptions.customizeText = undefined
                }
                if (_this.tooltip)
                    _this.tooltip.update(tooltipOptions);
                else
                    _this.tooltip = charts.factory.createTooltip(tooltipOptions, _this._tooltipGroup);
                _this.tooltip.draw();
                _this.tracker.tooltip = _this.tooltip;
                if (point) {
                    tooltipCoords = point.getTooltipCoords();
                    _this.tooltip.move(~~tooltipCoords.x, ~~tooltipCoords.y, tooltipCoords.offset, _this.tooltip.tooltipText, _this.tooltip.fillColor, _this.tooltip.className);
                    _this.tooltip.show()
                }
            },
            _prepareDrawOptions: function(drawOptions) {
                var animationOptions = this.option('animation'),
                    options;
                animationOptions = animationOptions === true ? this._defaultOptions().animation : animationOptions;
                options = $.extend({}, {
                    force: false,
                    adjustAxes: true,
                    drawLegend: true,
                    drawTitle: true,
                    adjustSeriesLabels: true,
                    animate: animationOptions.enabled,
                    animationPointsLimit: animationOptions.maxPointCountSupported,
                    asyncSeriesRendering: animationOptions.asyncSeriesRendering,
                    asyncTrackersRendering: animationOptions.asyncTrackersRendering,
                    trackerRenderingDelay: animationOptions.trackerRenderingDelay
                }, drawOptions);
                if (!utils.isDefined(options.recreateCanvas))
                    options.recreateCanvas = !(!options.adjustAxes || !options.drawLegend || !options.drawTitle);
                return options
            },
            _processRefreshData: function(newRefreshAction) {
                var currentRefreshActionPosition = $.inArray(this._currentRefreshData, ACTIONS_BY_PRIORITY),
                    newRefreshActionPosition = $.inArray(newRefreshAction, ACTIONS_BY_PRIORITY);
                if (!this._currentRefreshData || currentRefreshActionPosition >= 0 && newRefreshActionPosition < currentRefreshActionPosition)
                    this._currentRefreshData = newRefreshAction
            },
            _disposeSeries: function() {
                var _this = this;
                _this.tracker._clean();
                $.each(_this.series || [], function(_, series) {
                    series.dispose()
                });
                _this.series = null;
                $.each(_this.seriesFamilies || [], function(_, family) {
                    family.dispose()
                });
                _this.seriesFamilies = null
            },
            _optionChanged: function(name, value, prevValue) {
                var _this = this,
                    changedTitle;
                if (!_this._optionsInitializing) {
                    _this._optionValuesEqual(name, _this._userOptions[name], value);
                    dataUtils.compileSetter(name)(_this._userOptions, value, {
                        functionsAsIs: true,
                        merge: true
                    })
                }
                if (name === 'animation') {
                    _this.renderer.updateAnimationOptions(value);
                    return
                }
                clearTimeout(_this.delayedRedraw);
                switch (name) {
                    case'dataSource':
                        _this._needHandleRenderComplete = true;
                        _this._processRefreshData('_reinitDataSource');
                        break;
                    case'palette':
                        _this.themeManager.updatePalette(value);
                        _this._disposeSeries();
                        _this._needHandleRenderComplete = true;
                        _this._processRefreshData('_handleDataSourceChanged');
                        break;
                    case'series':
                    case'commonSeriesSettings':
                    case'backgroundColor':
                    case'dataPrepareSettings':
                        _this._disposeSeries();
                        _this._needHandleRenderComplete = true;
                        _this._processRefreshData('_handleDataSourceChanged');
                        break;
                    case'legend':
                    case'seriesTemplate':
                        _this._processRefreshData('_handleDataSourceChanged');
                        break;
                    case'title':
                        changedTitle = _this._processTitleOption(value, prevValue);
                        if (changedTitle) {
                            _this.option('title', prevValue);
                            return
                        }
                        _this._processRefreshData('force_render');
                        break;
                    case'valueAxis':
                    case'argumentAxis':
                    case'commonAxisSettings':
                        _this._needHandleRenderComplete = true;
                        _this._processRefreshData('processAxesOption');
                        _this._disposeSeries();
                        _this.paneAxis = {};
                        break;
                    case'panes':
                    case'defaultPane':
                        _this._disposeSeries();
                        _this.paneAxis = {};
                        _this._needHandleRenderComplete = true;
                        _this._processRefreshData('reinit');
                        break;
                    case'size':
                        _this._saveUserCanvas();
                        _this._processRefreshData('force_render');
                        break;
                    case'theme':
                        _this._initOptions(_this._userOptions);
                        _this._processRefreshData('reinit');
                        break;
                    default:
                        _this._processRefreshData('reinit')
                }
                _this._invalidate();
                _this.callBase.apply(_this, arguments)
            },
            _refresh: function() {
                var _this = this;
                _this._clean();
                if (_this._currentRefreshData) {
                    switch (_this._currentRefreshData) {
                        case'force_render':
                            _this._render({force: true});
                            break;
                        case'processAxesOption':
                            _this._processAxesOption(_this._options);
                            _this._reinit(true);
                            break;
                        case'reinit':
                            _this._reinit(true);
                            break;
                        default:
                            _this[_this._currentRefreshData] && _this[_this._currentRefreshData]()
                    }
                    delete _this._currentRefreshData
                }
                else
                    _this._render({force: true})
            },
            _dataSourceOptions: function() {
                return {
                        paginate: false,
                        _preferSync: true
                    }
            },
            _createCanvasClipRect: function() {
                var _this = this,
                    canvas = _this.canvas;
                if (!_this.canvasClipRect)
                    _this.canvasClipRect = _this.renderer.createClipRect(canvas.left, canvas.top, canvas.width - canvas.left - canvas.right, canvas.height - canvas.top - canvas.bottom).append();
                else
                    _this.canvasClipRect.updateRectangle({
                        x: canvas.left,
                        y: canvas.top,
                        width: canvas.width - canvas.left - canvas.right,
                        height: canvas.height - canvas.top - canvas.bottom
                    })
            },
            _getCanvasClipRectID: function() {
                return this.canvasClipRect.id
            },
            _handleDataSourceChanged: function() {
                this._dataSpecificInit(true)
            },
            _groupSeries: function() {
                this._groupedSeries = [this.series]
            },
            _dataSpecificInit: function(needRedraw) {
                this._initSeries();
                this._repopulateSeries();
                this._handleSeriesPopulated(needRedraw)
            },
            _processSeriesTemplate: function() {
                var _this = this,
                    seriesTemplate = _this.option('seriesTemplate'),
                    customizeSeries = utils.isFunction(seriesTemplate.customizeSeries) ? seriesTemplate.customizeSeries : $.noop,
                    nameField = seriesTemplate.nameField || 'series',
                    dataSource = _this._dataSource;
                if (!dataSource)
                    return;
                var generatedSeries = {},
                    seriesOrder = [],
                    items = dataSource.items(),
                    series;
                for (var i = 0, length = items.length; i < length; i++) {
                    var data = items[i];
                    if (nameField in data) {
                        series = generatedSeries[data[nameField]];
                        if (!series) {
                            series = generatedSeries[data[nameField]] = {
                                name: data[nameField],
                                data: []
                            };
                            seriesOrder.push(series.name)
                        }
                        series.data.push(data)
                    }
                }
                _this._templatedSeries = $.map(seriesOrder, function(orderedName) {
                    var group = generatedSeries[orderedName],
                        seriesOptions = customizeSeries.call(null, group.name);
                    return $.extend(group, seriesOptions)
                });
                _this._populateSeries();
                delete _this._templatedSeries
            },
            _processSingleSeries: function(){},
            _repopulateSeries: function() {
                var self = this,
                    parsedData,
                    rotated = self.option('rotated'),
                    incidentOccured = self.option('incidentOccured'),
                    data = self._dataSource && self._dataSource.items(),
                    dataValidatorOptions = this.option('dataPrepareSettings'),
                    seriesTemplate = this.option('seriesTemplate');
                if (this._dataSource && seriesTemplate) {
                    this._processSeriesTemplate();
                    data = self.teamplateData || data
                }
                this._groupSeries();
                self._dataValidator = charts.factory.createDataValidator(data, self._groupedSeries, incidentOccured, dataValidatorOptions);
                parsedData = self._dataValidator.validate();
                self.themeManager.resetPalette();
                $.each(self.series, function(_, singleSeries) {
                    singleSeries.reinitData(parsedData);
                    self._processSingleSeries(singleSeries, singleSeries.userOptions)
                })
            },
            _handleRenderComplete: function() {
                var _this = this,
                    userHandle = _this.option('done'),
                    allSeriesInited = true;
                if (_this._needHandleRenderComplete) {
                    $.each(_this.series, function(_, s) {
                        allSeriesInited = allSeriesInited && s.canRenderCompleteHandle()
                    });
                    if (allSeriesInited) {
                        _this._needHandleRenderComplete = false;
                        $.isFunction(userHandle) && userHandle.call(_this)
                    }
                }
            },
            getAllSeries: function getAllSeries() {
                return this.series.slice()
            },
            getSeriesByName: function getSeriesByName(name) {
                var found = null;
                $.each(this.series, function(i, singleSeries) {
                    if (singleSeries.name === name) {
                        found = singleSeries;
                        return false
                    }
                });
                return found
            },
            getSeriesByPos: function getSeriesByPos(pos) {
                return this.series[pos]
            },
            getSelectedSeries: function getSelectedSeries() {
                return null
            },
            clearSelection: function clearSelection() {
                this.tracker.clearSelection()
            },
            hideTooltip: function() {
                this.tracker._hideTooltip()
            },
            render: function(renderOptions) {
                this._render(renderOptions)
            }
        }).include(ui.DataHelperMixin).include(DX.viz.core.loadIndicatorAPI.base)
    })(jQuery, DevExpress);
    /*! Module viz-charts, file chart.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            charts = DX.viz.charts,
            utils = DX.utils,
            MAX_ADJUSTMENT_ATTEMPTS = 5,
            DEFAULT_PANE_NAME = 'default',
            DEFAULT_AXIS_NAME = 'defaultAxisName',
            DEFAULT_BUSINESS_RANGE_VALUE_MARGIN = 0.1;
        charts.Chart = charts.BaseChart.inherit({
            _defaultOptions: function() {
                return $.extend(true, this.callBase(), {
                        commonSeriesSettings: {
                            type: 'line',
                            maxLabelCount: undefined,
                            stack: 'default',
                            label: {
                                visible: false,
                                alignment: 'center',
                                rotationAngle: 0,
                                horizontalOffset: 0,
                                verticalOffset: 0,
                                radialOffset: 0,
                                format: '',
                                argumentFormat: '',
                                precision: 0,
                                argumentPrecision: 0,
                                percentPrecision: 0,
                                customizeText: undefined,
                                position: 'outside',
                                connector: {
                                    visible: false,
                                    width: 0
                                }
                            }
                        },
                        useAggregation: false,
                        defaultPane: DEFAULT_PANE_NAME,
                        adjustOnZoom: true,
                        rotated: false,
                        synchronizeMultiAxes: true,
                        equalBarWidth: true,
                        commonPaneSettings: {
                            backgroundColor: 'none',
                            border: {
                                visible: false,
                                top: true,
                                bottom: true,
                                left: true,
                                right: true,
                                dashStyle: 'solid'
                            }
                        },
                        panes: [{
                                name: DEFAULT_PANE_NAME,
                                border: {}
                            }],
                        commonAxisSettings: {
                            tickInterval: undefined,
                            setTicksAtUnitBeginning: true,
                            valueMarginsEnabled: true,
                            placeholderSize: null,
                            logarithmBase: 10
                        }
                    })
            },
            _dispose: function() {
                var _this = this,
                    disposeObjectsInArray = this._disposeObjectsInArray;
                _this.callBase();
                _this.panes = null;
                _this.legend && (_this.legend.dispose(), _this.legend = null);
                disposeObjectsInArray.call(_this, "panesBackground");
                disposeObjectsInArray.call(_this, "panesClipRects");
                disposeObjectsInArray.call(_this, "horizontalAxes");
                disposeObjectsInArray.call(_this, "verticalAxes");
                disposeObjectsInArray.call(_this, "seriesFamilies");
                $.each(_this._paneTrackerGroups || [], function(_, groups) {
                    groups.paneSeriesGroup.dispose();
                    groups.paneMarkerGroup.dispose()
                });
                _this._paneTrackerGroups = null
            },
            _init: function() {
                this.paneAxis = {};
                this._crossHairOptions = {};
                this.callBase()
            },
            _reinit: function(needRedraw) {
                var _this = this;
                _this._disposeObjectsInArray("translators");
                _this.translators = [];
                _this.panes = _this._createPanes();
                _this._populateAxes();
                _this.callBase();
                delete _this._seriesInitializing;
                if (!_this.series)
                    _this._dataSpecificInit();
                else
                    _this._correctValueAxes();
                needRedraw && _this._render({force: true})
            },
            _correctBusinessRange: function(range, tickInterval, field, setTicksAtUnitBeginning) {
                var min = 'min' + field,
                    max = 'max' + field;
                if (!tickInterval || !utils.isDefined(range[min]) || !utils.isDefined(range[max]))
                    return false;
                var tickIntervalRange = {},
                    originInterval = tickInterval;
                tickInterval = $.isNumeric(tickInterval) ? tickInterval : utils.convertDateTickIntervalToMilliseconds(tickInterval);
                if (tickInterval >= Math.abs(range[max] - range[min])) {
                    if (utils.isDate(range[min])) {
                        if (!$.isNumeric(originInterval)) {
                            tickIntervalRange[min] = utils.addInterval(range[min], originInterval, true);
                            tickIntervalRange[max] = utils.addInterval(range[max], originInterval, false)
                        }
                        else {
                            tickIntervalRange[min] = new Date(range[min].valueOf() - tickInterval);
                            tickIntervalRange[max] = new Date(range[max].valueOf() + tickInterval)
                        }
                        if (setTicksAtUnitBeginning) {
                            utils.correctDateWithUnitBeginning(tickIntervalRange[max], originInterval);
                            utils.correctDateWithUnitBeginning(tickIntervalRange[min], originInterval)
                        }
                    }
                    else {
                        tickIntervalRange[min] = range[min] - tickInterval;
                        tickIntervalRange[max] = range[max] + tickInterval
                    }
                    range.getBoundRange(tickIntervalRange);
                    return true
                }
                return false
            },
            _populateBusinessRange: function(visibleArea) {
                var self = this,
                    panes = self.panes,
                    businessRanges = [],
                    range,
                    i,
                    rotated = self.option('rotated'),
                    singleSeriesRange,
                    valAxes = rotated ? self.horizontalAxes : self.verticalAxes,
                    valueAxes = {},
                    argAxes = rotated ? self.verticalAxes : self.horizontalAxes,
                    valueField = rotated && 'X' || 'Y',
                    argumentField = rotated && 'Y' || 'X',
                    valueBoundRange = 'getBoundRange' + valueField,
                    argumentBoundRange = 'getBoundRange' + argumentField,
                    incidentOccured = self.option('incidentOccured'),
                    businessLength,
                    paneList = $.map(panes, function(pane) {
                        return pane.name
                    }),
                    series = self.series,
                    argumentTickInterval,
                    setTicksAtUnitBeginning,
                    paneAxis = self.paneAxis,
                    groupedSeries = self._groupedSeries;
                self._disposeObjectsInArray("businessRanges");
                var argRange = new charts.Range;
                $.each(valAxes, function(_, axis) {
                    valueAxes[axis.name] = axis
                });
                $.each(paneAxis, function(paneName, pane) {
                    $.each(pane, function(axisName, _) {
                        var seriesForRange = [],
                            valueAxesForRange,
                            valRange = new charts.Range({
                                pane: paneName,
                                axis: axisName,
                                minValueMarginX: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN,
                                maxValueMarginX: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN,
                                minValueMarginY: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN,
                                maxValueMarginY: DEFAULT_BUSINESS_RANGE_VALUE_MARGIN
                            }),
                            valueType,
                            calcInterval;
                        $.each(groupedSeries, function(_, particularSeriesGroup) {
                            if (particularSeriesGroup[0].pane === paneName && particularSeriesGroup[0].axis === axisName)
                                seriesForRange = particularSeriesGroup
                        });
                        $.each(valAxes, function(_, axis) {
                            if (axis.pane === paneName && axis.name === axisName) {
                                valueAxesForRange = axis;
                                return false
                            }
                        });
                        $.each(argAxes, function(_, axis) {
                            axis.validate(true, incidentOccured);
                            axis.options.type = seriesForRange && seriesForRange.length ? seriesForRange[0].options.argumentAxisType : null;
                            argRange = argRange[argumentBoundRange](axis.getRangeData());
                            argumentTickInterval = axis.options.tickInterval;
                            setTicksAtUnitBeginning = axis.options.setTicksAtUnitBeginning;
                            calcInterval = axis.calcInterval
                        });
                        valueAxesForRange.validate(false, incidentOccured);
                        valueAxesForRange.options.type = seriesForRange && seriesForRange.length ? seriesForRange[0].options.valueAxisType : null;
                        var axisRange = new charts.Range(valueAxesForRange.getRangeData());
                        axisRange.applyEqualLimitsMargins();
                        valueType = valueType || valueAxesForRange.options.valueType === 'datetime' ? 'datetime' : undefined;
                        valRange = valRange[valueBoundRange](axisRange);
                        for (i = 0; i < seriesForRange.length; i++) {
                            singleSeriesRange = seriesForRange[i].getRangeData(visibleArea, calcInterval);
                            valRange = valRange[valueBoundRange](singleSeriesRange);
                            argRange = argRange[argumentBoundRange](singleSeriesRange)
                        }
                        if (!valRange['isDefined' + valueField]())
                            valRange['setStubData' + valueField](valueType);
                        businessRanges.push(valRange)
                    })
                });
                if (!argRange['isDefined' + argumentField]())
                    argRange['setStubData' + argumentField](argAxes[0].options.argumentType);
                var bussinesRangeCorrectedWithTickInterval = self._correctBusinessRange(argRange, argumentTickInterval, argumentField, setTicksAtUnitBeginning);
                $.each(businessRanges, function(_, range) {
                    range = range.getBoundRange(argRange);
                    var vAxis = valueAxes[range.axis];
                    if (vAxis && vAxis.options.showZero)
                        range.correctValueZeroLevel();
                    !bussinesRangeCorrectedWithTickInterval && range.applyValueMargins();
                    range['stubData' + argumentField] = argRange['stubData' + argumentField];
                    if (!range.isDefined())
                        range.setStubData()
                });
                self.businessRanges = businessRanges
            },
            _groupSeries: function() {
                var self = this,
                    panes = self.panes,
                    rotated = self.option('rotated'),
                    valAxes = rotated ? self.horizontalAxes : self.verticalAxes,
                    argAxes = rotated ? self.verticalAxes : self.horizontalAxes,
                    paneList = $.map(panes, function(pane) {
                        return pane.name
                    }),
                    series = self.series,
                    paneAxis = self.paneAxis,
                    groupedSeries = self._groupedSeries = [];
                var getFirstAxisNameForPane = function(axes, paneName) {
                        var result;
                        for (var i = 0; i < axes.length; i++)
                            if (axes[i].pane === paneName) {
                                result = axes[i].name;
                                break
                            }
                        if (!result)
                            result = valAxes[0].name;
                        return result
                    };
                $.each(series, function(i, particularSeries) {
                    particularSeries.axis = particularSeries.axis || getFirstAxisNameForPane(valAxes, particularSeries.pane);
                    if (particularSeries.axis) {
                        paneAxis[particularSeries.pane] = paneAxis[particularSeries.pane] || {};
                        paneAxis[particularSeries.pane][particularSeries.axis] = true
                    }
                });
                $.each(valAxes, function(_, axis) {
                    if (axis.name && axis.pane && $.inArray(axis.pane, paneList) != -1) {
                        paneAxis[axis.pane] = paneAxis[axis.pane] || {};
                        paneAxis[axis.pane][axis.name] = true
                    }
                });
                self._correctValueAxes();
                var hideGridsOnNonFirstValueAxisForPane = function(paneName) {
                        var axesForPane = [],
                            firstShownAxis;
                        $.each(valAxes, function(_, axis) {
                            if (axis.pane === paneName)
                                axesForPane.push(axis)
                        });
                        if (axesForPane.length > 1 && self.option('synchronizeMultiAxes'))
                            $.each(axesForPane, function(_, axis) {
                                var gridOpt = axis.options.grid;
                                if (firstShownAxis && gridOpt && gridOpt.visible)
                                    gridOpt.visible = false;
                                else
                                    firstShownAxis = firstShownAxis ? firstShownAxis : gridOpt && gridOpt.visible
                            })
                    };
                $.each(paneAxis, function(paneName, pane) {
                    hideGridsOnNonFirstValueAxisForPane(paneName);
                    $.each(pane, function(axisName, _) {
                        var group = [];
                        $.each(series, function(_, particularSeries) {
                            if (particularSeries.pane === paneName && particularSeries.axis === axisName)
                                group.push(particularSeries)
                        });
                        group.length && groupedSeries.push(group)
                    })
                })
            },
            _createPanes: function() {
                var _this = this,
                    panes = _this.option('panes'),
                    bottomPaneName;
                $.each(_this.panesClipRects || [], function(i, clipRect) {
                    clipRect.remove()
                });
                _this.panesClipRects = [];
                _this.defaultPane = _this.option('defaultPane');
                panes = $.isArray(panes) ? panes : panes ? [panes] : [];
                if (!_this._doesPaneExists(panes, _this.defaultPane) && panes.length > 0) {
                    bottomPaneName = panes[panes.length - 1].name;
                    _this.option('incidentOccured')('Pane "' + _this.defaultPane + '" does not exist. Use pane "' + bottomPaneName + '" instead');
                    _this.defaultPane = bottomPaneName
                }
                if (_this.option('rotated'))
                    panes = panes.reverse();
                return panes
            },
            _doesPaneExists: function(panes, paneName) {
                var found = false;
                $.each(panes, function(_, pane) {
                    if (pane.name === paneName) {
                        found = true;
                        return false
                    }
                });
                return found
            },
            _populateSeries: function() {
                var _this = this,
                    hasSeriesTemplate = !!_this.option('seriesTemplate'),
                    series = hasSeriesTemplate ? _this._templatedSeries : _this.option('series'),
                    allSeriesOptions = $.isArray(series) ? series : series ? [series] : [],
                    argumentAxisOptions = _this.option('argumentAxis'),
                    valueAxisOptions = _this.option('valueAxis'),
                    themeManager = _this.themeManager,
                    data,
                    particularSeriesOptions,
                    commonSeriesSettings = _this.option('commonSeriesSettings'),
                    userCommonSeriesSettings = _this._userOptions.commonSeriesSettings,
                    particularSeries,
                    rotated = _this.option('rotated'),
                    incidentOccured = _this.option('incidentOccured'),
                    i,
                    paneList = $.map(_this.panes, function(pane) {
                        return pane.name
                    }),
                    paneName,
                    paneIndex;
                _this.teamplateData = [];
                $.each(_this._paneTrackerGroups || [], function(_, groups) {
                    groups.paneSeriesGroup.remove();
                    groups.paneMarkerGroup.remove()
                });
                _this._paneTrackerGroups = [];
                $.each(_this.panes, function(_, pane) {
                    var paneSeriesTrackerGroup = _this.renderer.createGroup({'class': 'dxc-pane-tracker'}),
                        paneMarkerTrackerGroup = _this.renderer.createGroup({'class': 'dxc-pane-tracker'});
                    _this._paneTrackerGroups.push({
                        paneSeriesGroup: paneSeriesTrackerGroup,
                        paneMarkerGroup: paneMarkerTrackerGroup
                    })
                });
                _this._disposeSeries();
                _this.series = [];
                themeManager.resetPalette();
                commonSeriesSettings.containerBackgroundColor = _this.option('containerBackgroundColor');
                for (i = 0; i < allSeriesOptions.length; i++) {
                    particularSeriesOptions = allSeriesOptions[i];
                    if (particularSeriesOptions.type && !utils.isString(particularSeriesOptions.type))
                        particularSeriesOptions.type = '';
                    data = particularSeriesOptions.data;
                    particularSeriesOptions.data = null;
                    particularSeriesOptions.rotated = rotated;
                    particularSeriesOptions.customizePoint = _this._userOptions.customizePoint;
                    if (argumentAxisOptions) {
                        particularSeriesOptions.argumentCategories = argumentAxisOptions.categories;
                        particularSeriesOptions.argumentAxisType = argumentAxisOptions.type;
                        particularSeriesOptions.argumentType = argumentAxisOptions.argumentType
                    }
                    if (valueAxisOptions)
                        if (utils.isArray(valueAxisOptions))
                            $.each(valueAxisOptions, function(iter, options) {
                                if (!particularSeriesOptions.axis && !iter || particularSeriesOptions.axis === options.name) {
                                    particularSeriesOptions.valueCategories = options.categories;
                                    particularSeriesOptions.valueAxisType = options.type;
                                    particularSeriesOptions.valueType = options.valueType
                                }
                            });
                        else {
                            particularSeriesOptions.valueCategories = valueAxisOptions.categories;
                            particularSeriesOptions.valueAxisType = valueAxisOptions.type;
                            particularSeriesOptions.valueType = valueAxisOptions.valueType
                        }
                    particularSeriesOptions.incidentOccured = incidentOccured;
                    if (!particularSeriesOptions.name)
                        particularSeriesOptions.name = 'Series ' + (i + 1).toString();
                    var seriesTheme = themeManager.applyNextSeriesTheme(particularSeriesOptions, commonSeriesSettings, userCommonSeriesSettings);
                    seriesTheme.pane = seriesTheme.pane || _this.defaultPane;
                    paneName = seriesTheme.pane;
                    paneIndex = _this._getPaneIndex(paneName);
                    if ($.inArray(paneName, paneList) === -1)
                        continue;
                    seriesTheme.seriesGroup = _this._seriesGroup;
                    seriesTheme.seriesLabelsGroup = _this._labelsGroup;
                    seriesTheme.seriesTrackerGroup = _this._paneTrackerGroups[paneIndex].paneSeriesGroup;
                    seriesTheme.markerTrackerGroup = _this._paneTrackerGroups[paneIndex].paneMarkerGroup;
                    particularSeries = charts.factory.createSeries(seriesTheme.type, _this.renderer, seriesTheme);
                    if (!particularSeries)
                        incidentOccured.call(null, 'Unknown series type requested: ' + seriesTheme.type);
                    else {
                        particularSeries.index = i;
                        _this.series.push(particularSeries)
                    }
                    if (hasSeriesTemplate) {
                        $.each(data, function(_, data) {
                            $.each(particularSeries.getTeamplatedFields(), function(_, field) {
                                data[field.teamplateField] = data[field.originalField]
                            });
                            _this.teamplateData.push(data)
                        });
                        particularSeries.updateTeamplateFieldNames()
                    }
                }
                return _this.series
            },
            _createValueAxis: function(axisOptions, rotated, tickProvider) {
                var _this = this,
                    axis;
                axisOptions = $.extend({
                    isHorizontal: rotated,
                    tickProvider: tickProvider,
                    incidentOccured: _this.option('incidentOccured')
                }, axisOptions);
                axisOptions = $.extend(true, {}, _this.option('commonAxisSettings'), _this.option(rotated ? 'horizontalAxis' : 'verticalAxis'), _this.option('valueAxisStyle'), _this.option('userCommonAxisSettings'), _this.option('valueAxis'), axisOptions);
                if (axisOptions.strips)
                    $.each(axisOptions.strips, function(i, strips) {
                        axisOptions.strips[i] = $.extend(true, {}, axisOptions.stripStyle, axisOptions.strips[i])
                    });
                if (axisOptions.constantLines)
                    $.each(axisOptions.constantLines, function(i, line) {
                        axisOptions.constantLines[i] = $.extend(true, {}, axisOptions.constantLineStyle, line)
                    });
                axis = charts.factory.createAxis(_this.renderer, axisOptions);
                axis.name = axisOptions.name;
                axis.pane = axis.pane || axisOptions.pane;
                axis.priority = axisOptions.priority;
                return axis
            },
            _disposeAxes: function() {
                var _this = this;
                $.each(_this.horizontalAxes || [], function(_, axis) {
                    axis.dispose()
                });
                $.each(_this.verticalAxes || [], function(_, axis) {
                    axis.dispose()
                });
                _this.horizontalAxes = null;
                _this.verticalAxes = null
            },
            _populateAxes: function() {
                var _this = this,
                    horizontalAxes = [],
                    verticalAxes = [],
                    panes = _this.panes,
                    rotated = _this.option('rotated'),
                    themeManager = _this.themeManager,
                    valueAxisOptions = _this.option('valueAxis') || {},
                    argumentOption = _this.option('argumentAxis') || {},
                    argumentAxesOptions = $.isArray(argumentOption) ? argumentOption : [argumentOption],
                    valueAxesOptions = $.isArray(valueAxisOptions) ? valueAxisOptions : [valueAxisOptions],
                    i,
                    axis,
                    axisNames = [],
                    axisOptions,
                    tickProvider = charts.factory.getAxisTickProvider(),
                    paneWithNonVirtualAxis;
                _this._disposeAxes();
                var createArgumentAxis = function(axisOptions, virtual) {
                        axisOptions = $.extend(true, {
                            isHorizontal: !rotated,
                            tickProvider: tickProvider,
                            pane: _this.defaultPane,
                            incidentOccured: _this.option('incidentOccured')
                        }, axisOptions);
                        axisOptions = $.extend(true, {}, _this.option('commonAxisSettings'), _this.option(rotated ? 'verticalAxis' : 'horizontalAxis'), _this.option('argumentAxisStyle'), _this.option('userCommonAxisSettings'), _this.option('argumentAxis'), axisOptions);
                        if (axisOptions.strips)
                            $.each(axisOptions.strips, function(i, strips) {
                                axisOptions.strips[i] = $.extend(true, {}, axisOptions.stripStyle, axisOptions.strips[i])
                            });
                        if (axisOptions.constantLines)
                            $.each(axisOptions.constantLines, function(i, line) {
                                axisOptions.constantLines[i] = $.extend(true, {}, axisOptions.constantLineStyle, line)
                            });
                        axis = charts.factory.createAxis(_this.renderer, axisOptions);
                        axis._virtual = virtual;
                        if (axisOptions.isHorizontal)
                            horizontalAxes.push(axis);
                        else
                            verticalAxes.push(axis)
                    };
                if (rotated)
                    paneWithNonVirtualAxis = argumentAxesOptions[0].position === 'right' ? panes[panes.length - 1].name : panes[0].name;
                else
                    paneWithNonVirtualAxis = argumentAxesOptions[0].position === 'top' ? panes[0].name : panes[panes.length - 1].name;
                $.each(panes, function(_, pane) {
                    var paneName = pane.name,
                        virtual = paneName != paneWithNonVirtualAxis;
                    var axisOptions = $.extend(true, {}, {pane: paneName}, argumentAxesOptions[0]);
                    createArgumentAxis(axisOptions, virtual)
                });
                var createValueAxis = function(axisOptions) {
                        var axis = _this._createValueAxis(axisOptions, rotated, tickProvider);
                        if (rotated)
                            horizontalAxes.push(axis);
                        else
                            verticalAxes.push(axis)
                    };
                var valueAxesCounter = 0;
                var getNextAxisName = function() {
                        return DEFAULT_AXIS_NAME + valueAxesCounter++
                    };
                var unique = function(array) {
                        var values = {},
                            i,
                            len = array.length;
                        for (i = 0; i < len; i++)
                            values[array[i]] = true;
                        return $.map(values, function(_, key) {
                                return key
                            })
                    };
                $.each(valueAxesOptions, function(priority, axisOptions) {
                    var axisPanes = [],
                        name = axisOptions.name;
                    if (name && $.inArray(name, axisNames) != -1) {
                        _this.option('incidentOccured').call(null, 'The "valueAxis" configuration array contains axes with the same name.');
                        return
                    }
                    name && axisNames.push(name);
                    if (axisOptions.pane)
                        axisPanes.push(axisOptions.pane);
                    if (axisOptions.panes && axisOptions.panes.length)
                        axisPanes = axisPanes.concat(axisOptions.panes.slice(0));
                    axisPanes = unique(axisPanes);
                    if (!axisPanes.length)
                        axisPanes.push(undefined);
                    $.each(axisPanes, function(_, pane) {
                        createValueAxis($.extend(true, {}, axisOptions, {
                            name: name || getNextAxisName(),
                            pane: pane,
                            priority: priority
                        }))
                    })
                });
                _this.horizontalAxes = horizontalAxes;
                _this.verticalAxes = verticalAxes
            },
            _correctValueAxes: function() {
                var _this = this,
                    rotated = _this.option('rotated'),
                    themeManager = _this.themeManager,
                    valueAxisOptions = _this.option('valueAxis') || {},
                    valueAxesOptions = $.isArray(valueAxisOptions) ? valueAxisOptions : [valueAxisOptions],
                    tickProvider = charts.factory.getAxisTickProvider(),
                    valueAxes = (rotated ? _this.horizontalAxes : _this.verticalAxes) || [],
                    defaultAxisName = valueAxes[0].name,
                    paneAxis = _this.paneAxis || {},
                    panes = _this.panes,
                    i,
                    neededAxis = {};
                var getPaneForAxis = function(axisNameWithoutPane) {
                        var result;
                        $.each(_this.paneAxis, function(paneName, pane) {
                            $.each(pane, function(axisName, _) {
                                if (axisNameWithoutPane == axisName) {
                                    result = paneName;
                                    return false
                                }
                            })
                        });
                        return result
                    };
                var axesWithoutPanes = $.map(valueAxes, function(axis) {
                        if (axis.pane)
                            return null;
                        return axis
                    });
                $.each(axesWithoutPanes, function(_, axis) {
                    axis.pane = getPaneForAxis(axis.name);
                    if (!axis.pane) {
                        axis.pane = _this.defaultPane;
                        paneAxis[axis.pane] = paneAxis[axis.pane] || {};
                        paneAxis[axis.pane][axis.name] = true
                    }
                    axis.options.pane = axis.pane
                });
                for (i = 0; i < panes.length; i++)
                    if (!paneAxis[panes[i].name]) {
                        paneAxis[panes[i].name] = {};
                        paneAxis[panes[i].name][defaultAxisName] = true
                    }
                var findAxisOptions = function(axisName) {
                        var result,
                            axInd;
                        for (axInd = 0; axInd < valueAxesOptions.length; axInd++)
                            if (valueAxesOptions[axInd].name == axisName) {
                                result = valueAxisOptions[axInd];
                                result.priority = axInd;
                                break
                            }
                        if (!result)
                            for (axInd = 0; axInd < valueAxes.length; axInd++)
                                if (valueAxes[axInd].name == axisName) {
                                    result = valueAxes[axInd].options;
                                    result.priority = valueAxes[axInd].priority;
                                    break
                                }
                        if (!result) {
                            _this.option('incidentOccured').call(null, 'Value axis with the "' + axisName + '" name does not exist. It was created.');
                            result = {
                                name: axisName,
                                priority: valueAxes.length
                            }
                        }
                        return result
                    };
                var findAxis = function(paneName, axisName) {
                        var axis;
                        for (i = 0; i < valueAxes.length; i++) {
                            axis = valueAxes[i];
                            if (axis.name === axisName && axis.pane === paneName)
                                return axis
                        }
                    };
                $.each(_this.paneAxis, function(paneName, axisNames) {
                    $.each(axisNames, function(axisName, _) {
                        neededAxis[axisName + '-' + paneName] = true;
                        if (!findAxis(paneName, axisName)) {
                            var axisOptions = findAxisOptions(axisName);
                            if (axisOptions)
                                valueAxes.push(_this._createValueAxis($.extend(true, {}, axisOptions, {
                                    pane: paneName,
                                    name: axisName
                                }), rotated, tickProvider))
                        }
                    })
                });
                valueAxes = $.grep(valueAxes, function(elem) {
                    return !!neededAxis[elem.name + '-' + elem.pane]
                });
                valueAxes.sort(function(a, b) {
                    return a.priority - b.priority
                });
                rotated ? _this.horizontalAxes = valueAxes : _this.verticalAxes = valueAxes
            },
            _processSeriesFamilies: function() {
                var _this = this,
                    types = [],
                    families = [],
                    paneSeries,
                    rotated = _this.option('rotated');
                if (_this.seriesFamilies && _this.seriesFamilies.length) {
                    $.each(_this.seriesFamilies, function(_, family) {
                        family.adjustSeriesValues()
                    });
                    return
                }
                $.each(_this.series, function(_, item) {
                    if ($.inArray(item.type, types) === -1)
                        types.push(item.type)
                });
                $.each(_this.panes, function(_, pane) {
                    paneSeries = [];
                    $.each(_this.series, function(_, oneSeries) {
                        if (oneSeries.pane === pane.name)
                            paneSeries.push(oneSeries)
                    });
                    $.each(types, function(_, type) {
                        var family = charts.factory.createSeriesFamily({
                                type: type,
                                pane: pane.name,
                                rotated: rotated,
                                equalBarWidth: _this.option('equalBarWidth')
                            });
                        family.add(paneSeries);
                        family.adjustSeriesValues();
                        families.push(family)
                    })
                });
                _this.seriesFamilies = families
            },
            _createLegend: function() {
                var _this = this,
                    legendOptions = $.extend(true, {
                        renderer: _this.renderer,
                        series: _this.series,
                        containerBackgroundColor: _this.option('commonSeriesSettings').containerBackgroundColor
                    }, _this.option('legend'));
                if (_this.legend)
                    _this.legend.update(legendOptions);
                else
                    _this.legend = charts.factory.createLegend(legendOptions, _this._legendGroup, _this._legendTrackerGroup)
            },
            _createTranslator: function(range, canvas) {
                return new DX.viz.core.Translator2D(range, canvas)
            },
            _createPanesBorderOptions: function() {
                var commonBorderOptions = this.option('commonPaneSettings').border,
                    panesBorderOptions = {};
                $.each(this.panes, function(_, pane) {
                    var borderOptions = $.extend(true, {}, commonBorderOptions, pane.border);
                    panesBorderOptions[pane.name] = borderOptions
                });
                return panesBorderOptions
            },
            _render: function(drawOptions) {
                var _this = this,
                    renderer = _this.renderer,
                    translators = _this.translators,
                    rotated = _this.option('rotated'),
                    i,
                    layoutManager = _this.layoutManager,
                    titleOptions = _this.option('title'),
                    adjustmentCounter = 0,
                    paneName,
                    multiAxesSynchronizer = new charts.MultiAxesSynchronizer,
                    panesBorderOptions = _this._createPanesBorderOptions();
                var updateAxesPerPane = function(_this, axes) {
                        var translator,
                            axis,
                            axisName,
                            i;
                        for (i = 0; i < axes.length; i++) {
                            axis = axes[i];
                            paneName = axis.pane;
                            axisName = axis.name;
                            translator = _this._getTranslator(paneName, axisName);
                            if (translator) {
                                translator.init();
                                axis.setRange(translator.getBusinessRange());
                                axis.setTranslator(translator)
                            }
                        }
                    };
                var drawSeries = function drawSeries() {
                        var particularSeries,
                            i;
                        $.each(_this.seriesFamilies || [], function(_, seriesFamily) {
                            var translator = _this._getTranslator(seriesFamily.pane);
                            seriesFamily.updateSeriesValues(translator);
                            seriesFamily.adjustSeriesDimensions(translator);
                            seriesFamily.preparePointsForSharedTooltip(_this.option('tooltip'))
                        });
                        _this._createCrossHairCursor();
                        function applyPaneClipRect(seriesOptions) {
                            var paneIdx = _this._getPaneIndex(seriesOptions.pane);
                            seriesOptions.paneClipRectID = _this.panesClipRects[paneIdx].id;
                            seriesOptions.forceClipping = _this._getPaneBorderVisibility(paneIdx)
                        }
                        for (i = 0; i < _this.series.length; i++) {
                            particularSeries = _this.series[i];
                            applyPaneClipRect(particularSeries);
                            particularSeries.adjustSeriesLabels = drawOptions.adjustSeriesLabels;
                            particularSeries.draw(_this._getTranslator(particularSeries.pane, particularSeries.axis), drawOptions.animate && particularSeries.getPoints().length <= drawOptions.animationPointsLimit && _this.renderer.animationEnabled())
                        }
                        if (drawOptions.drawLegend && _this.legend && _this.legend.options.position === 'inside') {
                            _this.legend.canvas = _this.canvas;
                            _this._legendGroup.append();
                            _this._tooltipGroup.append();
                            _this.legend.draw();
                            layoutManager.applyLegendLayout()
                        }
                        else
                            _this.legend.options.position == 'inside' && _this.legend.toForeground();
                        _this.option('drawn')();
                        var drawChartTrackers = function drawChartTrackers() {
                                var i;
                                $.each(_this._paneTrackerGroups || [], function(_, groups) {
                                    groups.paneSeriesGroup.clear();
                                    groups.paneMarkerGroup.clear()
                                });
                                for (i = 0; i < _this.series.length; i++)
                                    _this.series[i].drawTrackers();
                                _this.legend && _this.legend.drawTrackers();
                                _this.tracker._prepare();
                                _this._trackerGroup.append();
                                $.each(_this._paneTrackerGroups, function(index, paneGroups) {
                                    paneGroups.paneSeriesGroup.append(_this._seriesTrackerGroup);
                                    paneGroups.paneMarkerGroup.append(_this._markerTrackerGroup)
                                });
                                _this._handleRenderComplete()
                            };
                        _this._createTooltip();
                        if (drawOptions.asyncTrackersRendering)
                            _this.delayedRedraw = setTimeout(drawChartTrackers, drawOptions.trackerRenderingDelay);
                        else
                            drawChartTrackers()
                    };
                drawOptions = _this._prepareDrawOptions(drawOptions);
                _this.callBase(drawOptions);
                if (_this.stopRedraw) {
                    _this.stopRedraw = false;
                    return
                }
                _this._createPanesBackground();
                if (titleOptions.text && drawOptions.drawTitle) {
                    _this._titleGroup.append();
                    _this._drawTitle();
                    layoutManager.applyTitleLayout()
                }
                if (drawOptions.drawLegend && _this.legend && _this.legend.options.position === 'outside') {
                    _this.legend.canvas = _this.canvas;
                    _this._legendGroup.append();
                    _this.legend.draw();
                    layoutManager.applyLegendLayout();
                    if (layoutManager.isCanvasExceeded(false)) {
                        _this.option('incidentOccured')('Container is too small to draw chart with current settings');
                        _this._clean();
                        return
                    }
                }
                _this._setPanesClipRectPadding(panesBorderOptions, rotated);
                if (drawOptions.recreateCanvas) {
                    layoutManager.createPanesCanvases(panesBorderOptions);
                    $.each(_this.paneAxis, function(paneName, pane) {
                        $.each(pane, function(axisName, _) {
                            var translator = _this._createTranslator(new charts.Range(_this._getBusinessRange(paneName, axisName)), _this._getCanvasForPane(paneName));
                            translator.pane = paneName;
                            translator.axis = axisName;
                            translators.push(translator)
                        })
                    })
                }
                _this._options.useAggregation && $.each(_this.series, function(_, series) {
                    series.resamplePoints(_this._getTranslator(series.pane), _this._zoomMinArg, _this._zoomMaxArg)
                });
                if (_this.option('adjustOnZoom') && (_this._zoomMinArg || _this._zoomMaxArg))
                    _this._populateBusinessRange({
                        minArg: _this._zoomMinArg,
                        maxArg: _this._zoomMaxArg
                    });
                $.each(translators, function(_, translator) {
                    translator.updateBusinessRange(new charts.Range(_this._getBusinessRange(translator.pane, translator.axis)));
                    delete translator._originalBusinessRange;
                    if (_this._zoomMinArg || _this._zoomMaxArg)
                        if (_this._options.rotated)
                            translator.zoomY(_this._zoomMinArg, _this._zoomMaxArg);
                        else
                            translator.zoomX(_this._zoomMinArg, _this._zoomMaxArg);
                    translator.init()
                });
                updateAxesPerPane(_this, _this.horizontalAxes);
                updateAxesPerPane(_this, _this.verticalAxes);
                _this._stripsGroup.append();
                _this._constantLinesGroup.append();
                _this._axesGroup.append();
                do {
                    for (i = 0; i < _this.horizontalAxes.length; i++)
                        _this.horizontalAxes[i].resetTicks();
                    for (i = 0; i < _this.verticalAxes.length; i++)
                        _this.verticalAxes[i].resetTicks();
                    if (_this.option('synchronizeMultiAxes'))
                        multiAxesSynchronizer.synchronize(rotated ? _this.horizontalAxes : _this.verticalAxes, rotated);
                    for (i = 0; i < _this.horizontalAxes.length; i++) {
                        _this.horizontalAxes[i].clipRectID = _this._getCanvasClipRectID();
                        _this.horizontalAxes[i].stripsGroup = _this._stripsGroup;
                        _this.horizontalAxes[i].constantLinesGroup = _this._constantLinesGroup;
                        _this.horizontalAxes[i].axesContainerGroup = _this._axesGroup;
                        _this.horizontalAxes[i].draw({borderOptions: panesBorderOptions[_this.horizontalAxes[i].pane]})
                    }
                    layoutManager.requireAxesRedraw = false;
                    if (drawOptions.adjustAxes) {
                        layoutManager.applyHorizontalAxesLayout();
                        $.each(translators, function(_, translator) {
                            translator.init()
                        })
                    }
                    for (i = 0; i < _this.verticalAxes.length; i++) {
                        _this.verticalAxes[i].clipRectID = _this._getCanvasClipRectID();
                        _this.verticalAxes[i].stripsGroup = _this._stripsGroup;
                        _this.verticalAxes[i].constantLinesGroup = _this._constantLinesGroup;
                        _this.verticalAxes[i].axesContainerGroup = _this._axesGroup;
                        _this.verticalAxes[i].draw({borderOptions: panesBorderOptions[_this.verticalAxes[i].pane]})
                    }
                    if (drawOptions.adjustAxes) {
                        layoutManager.applyVerticalAxesLayout();
                        $.each(translators, function(_, translator) {
                            translator.init()
                        })
                    }
                    adjustmentCounter = adjustmentCounter + 1;
                    if (layoutManager.isCanvasExceeded(true)) {
                        _this.option('incidentOccured')('Container is too small to draw chart with current settings');
                        _this._clean();
                        _this.__axisAdjustmentsCount = adjustmentCounter;
                        return
                    }
                } while (layoutManager.requireAxesRedraw && adjustmentCounter < MAX_ADJUSTMENT_ATTEMPTS);
                _this.__axisAdjustmentsCount = adjustmentCounter;
                if (_this.chartTitle)
                    _this.chartTitle.setClipRectSettings();
                _this._drawPanesBorders(panesBorderOptions);
                _this._createClipRectsForPanes();
                for (i = 0; i < _this.horizontalAxes.length; i++)
                    _this.horizontalAxes[i].applyClipRect(_this._getElementsClipRectID(_this.horizontalAxes[i].pane));
                for (i = 0; i < _this.verticalAxes.length; i++)
                    _this.verticalAxes[i].applyClipRect(_this._getElementsClipRectID(_this.verticalAxes[i].pane));
                _this._fillPanesBackground();
                _this._seriesGroup.append();
                _this._labelsGroup.append();
                _this._tooltipGroup.append();
                _this._crossHairCursorGroup.append();
                if (drawOptions.asyncSeriesRendering)
                    _this.delayedRedraw = setTimeout(drawSeries, 25);
                else
                    drawSeries()
            },
            _isInBarTypes: function(type) {
                return type.slice(-3) === 'bar' ? true : false
            },
            _setPanesClipRectPadding: function(panesBorderOptions, rotated) {
                var _this = this,
                    allPanesHaveBorder = true,
                    position = '';
                $.each(_this.panes, function(_, pane) {
                    allPanesHaveBorder = allPanesHaveBorder && !!panesBorderOptions[pane.name].visible
                });
                $.each(_this.horizontalAxes, function(_, axis) {
                    position += axis.options.position
                });
                $.each(_this.verticalAxes, function(_, axis) {
                    position += axis.options.position
                })
            },
            _createCrossHairCursor: function() {
                var _this = this,
                    renderer = _this.renderer,
                    panes = _this.panes,
                    commonCanvas,
                    canvas,
                    options = _this.option('crosshair') || {},
                    hLine,
                    vLine,
                    attrHLine,
                    attrVLine,
                    i;
                if (!options || !options.enabled)
                    return;
                attrHLine = {
                    stroke: options.horizontalLine.color || options.color,
                    strokeWidth: options.horizontalLine.width || options.width,
                    dashStyle: options.horizontalLine.dashStyle || options.dashStyle,
                    visibility: 'hidden',
                    opacity: options.horizontalLine.opacity || options.opacity
                };
                attrVLine = {
                    stroke: options.verticalLine.color || options.color,
                    strokeWidth: options.verticalLine.width || options.width,
                    dashStyle: options.verticalLine.dashStyle || options.dashStyle,
                    visibility: 'hidden',
                    opacity: options.verticalLine.opacity || options.opacity
                };
                for (i = 0; i < panes.length; i++) {
                    canvas = panes[i].canvas;
                    if (!commonCanvas)
                        commonCanvas = $.extend({}, canvas);
                    else {
                        commonCanvas.right = canvas.right;
                        commonCanvas.bottom = canvas.bottom
                    }
                    renderer.createRect(canvas.left, canvas.top, canvas.width - canvas.right - canvas.left, canvas.height - canvas.bottom - canvas.top, 0).append(this._crosshairTrackerGroup)
                }
                if (options.horizontalLine && options.horizontalLine.visible)
                    hLine = renderer.createLine(commonCanvas.left, commonCanvas.top, commonCanvas.width - commonCanvas.right, commonCanvas.top, attrHLine).append(_this._crossHairCursorGroup);
                if (options.verticalLine && options.verticalLine.visible)
                    vLine = renderer.createLine(commonCanvas.left, commonCanvas.top, commonCanvas.left, commonCanvas.height - commonCanvas.bottom, attrVLine).append(_this._crossHairCursorGroup);
                _this._crossHairOptions.horizontalLine = hLine;
                _this._crossHairOptions.verticalLine = vLine;
                _this._crossHairOptions.canvas = commonCanvas
            },
            _createPanesBackground: function() {
                var _this = this,
                    defaultBackgroundColor = _this.option('commonPaneSettings').backgroundColor,
                    backgroundColor,
                    renderer = _this.renderer,
                    rect,
                    i,
                    rects = [];
                _this._panesBackgroundGroup && _this._panesBackgroundGroup.clear();
                for (i = 0; i < _this.panes.length; i++) {
                    backgroundColor = _this.panes[i].backgroundColor || defaultBackgroundColor;
                    if (!backgroundColor || backgroundColor === 'none') {
                        rects.push(null);
                        continue
                    }
                    rect = renderer.createRect(0, 0, 0, 0, 0, {
                        fill: backgroundColor,
                        strokeWidth: 0
                    }).append(_this._panesBackgroundGroup);
                    rects.push(rect)
                }
                _this.panesBackground = rects;
                _this._panesBackgroundGroup.append()
            },
            _fillPanesBackground: function() {
                var _this = this,
                    bc;
                $.each(_this.panes, function(i, pane) {
                    bc = pane.borderCoords;
                    if (_this.panesBackground[i] != null)
                        _this.panesBackground[i].applySettings({
                            x: bc.left,
                            y: bc.top,
                            width: bc.width,
                            height: bc.height
                        })
                })
            },
            _calcPaneBorderCoords: function(pane, rotated) {
                var canvas = pane.canvas,
                    bc = pane.borderCoords = pane.borderCoords || {};
                bc.left = canvas.left;
                bc.top = canvas.top;
                bc.right = canvas.width - canvas.right;
                bc.bottom = canvas.height - canvas.bottom;
                bc.width = bc.right - bc.left;
                bc.height = bc.bottom - bc.top
            },
            _drawPanesBorders: function(panesBorderOptions) {
                var _this = this,
                    rotated = _this.option('rotated');
                _this._panesBorderGroup && (_this._panesBorderGroup.detach(), _this._panesBorderGroup.clear());
                $.each(_this.panes, function(i, pane) {
                    var bc,
                        borderOptions = panesBorderOptions[pane.name],
                        attr = {
                            fill: 'none',
                            stroke: borderOptions.color,
                            strokeOpacity: borderOptions.opacity,
                            strokeWidth: borderOptions.width,
                            dashStyle: borderOptions.dashStyle
                        };
                    _this._calcPaneBorderCoords(pane, rotated);
                    if (!borderOptions.visible)
                        return;
                    bc = pane.borderCoords;
                    _this.renderer.createSegmentRect(bc.left, bc.top, bc.width, bc.height, 0, borderOptions, attr).append(_this._panesBorderGroup)
                });
                _this._panesBorderGroup.append()
            },
            _createClipRectsForPanes: function() {
                var _this = this;
                $.each(_this.panes, function(i, pane) {
                    var bc = pane.borderCoords,
                        clipRect = _this.panesClipRects[i];
                    if (!clipRect) {
                        clipRect = _this.renderer.createClipRect(bc.left, bc.top, bc.width, bc.height).append();
                        _this.panesClipRects.push(clipRect)
                    }
                    else
                        clipRect.updateRectangle({
                            x: bc.left,
                            y: bc.top,
                            width: bc.width,
                            height: bc.height
                        })
                })
            },
            _getPaneIndex: function(paneName) {
                var paneIndex;
                $.each(this.panes, function(index, pane) {
                    if (pane.name === paneName) {
                        paneIndex = index;
                        return false
                    }
                });
                return paneIndex
            },
            _getPaneBorderVisibility: function(paneIndex) {
                var commonPaneBorderVisible = this.option('commonPaneSettings').border.visible,
                    pane = this.panes[paneIndex] || {},
                    paneBorder = pane.border || {};
                return 'visible' in paneBorder ? paneBorder.visible : commonPaneBorderVisible
            },
            _getElementsClipRectID: function(paneName) {
                return this.panesClipRects[this._getPaneIndex(paneName)].id
            },
            _getTranslator: function(paneName, axisName) {
                var translators = this.translators,
                    translatorsNumber = translators.length,
                    foundTranslator = null,
                    i;
                for (i = 0; i < translatorsNumber; i++)
                    if (translators[i].pane === paneName && translators[i].axis === axisName) {
                        foundTranslator = translators[i];
                        break
                    }
                if (!foundTranslator)
                    for (i = 0; i < translatorsNumber; i++)
                        if (translators[i].pane === paneName) {
                            foundTranslator = translators[i];
                            break
                        }
                return foundTranslator
            },
            _getCanvasForPane: function(paneName) {
                var panes = this.panes,
                    panesNumber = panes.length,
                    i;
                for (i = 0; i < panesNumber; i++)
                    if (panes[i].name === paneName)
                        return panes[i].canvas
            },
            _getBusinessRange: function(paneName, axisName) {
                var ranges = this.businessRanges || [],
                    rangesNumber = ranges.length,
                    foundRange,
                    i;
                for (i = 0; i < rangesNumber; i++)
                    if (ranges[i].pane === paneName && ranges[i].axis === axisName) {
                        foundRange = ranges[i];
                        break
                    }
                if (!foundRange)
                    for (i = 0; i < rangesNumber; i++)
                        if (ranges[i].pane === paneName) {
                            foundRange = ranges[i];
                            break
                        }
                return foundRange
            },
            _handleSeriesPopulated: function(needRedraw) {
                var _this = this;
                _this._processSeriesFamilies();
                _this._createLegend();
                _this._populateBusinessRange();
                _this._processValueAxisFormat();
                _this._updateTracker();
                needRedraw && _this._render({force: true})
            },
            _processValueAxisFormat: function() {
                var _this = this,
                    valueAxes = _this.option('rotated') ? _this.horizontalAxes : _this.verticalAxes,
                    axesWithFullStackedFormat = [];
                $.each(_this.series, function() {
                    if (this.isFullStackedSeries() && $.inArray(this.axis, axesWithFullStackedFormat) === -1)
                        axesWithFullStackedFormat.push(this.axis)
                });
                $.each(valueAxes, function() {
                    if ($.inArray(this.name, axesWithFullStackedFormat) !== -1)
                        this.setPercentLabelFormat();
                    else
                        this.resetAutoLabelFormat()
                })
            },
            zoomArgument: function(min, max) {
                var _this = this;
                _this._zoomMinArg = min;
                _this._zoomMaxArg = max;
                _this._render({
                    force: true,
                    drawTitle: false,
                    drawLegend: false,
                    adjustAxes: false,
                    animate: false,
                    adjustSeriesLabels: false,
                    asyncSeriesRendering: false
                })
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-charts, file pieChart.js */
    (function($, DX, undefined) {
        var core = DX.viz.core,
            charts = DX.viz.charts,
            utils = DX.utils,
            PANE_CLIP_RECT_PADDING = 12;
        charts.PieChart = charts.BaseChart.inherit({
            _defaultOptions: function() {
                return $.extend(true, this.callBase(), {
                        commonSeriesSettings: {
                            type: 'pie',
                            pie: {label: {percentPrecision: 0}}
                        },
                        legend: {hoverMode: 'markPoint'}
                    })
            },
            _reinit: function(needRedraw) {
                var _this = this;
                _this.callBase();
                if (!_this.series)
                    _this._dataSpecificInit();
                needRedraw && _this._render({force: true})
            },
            _populateBusinessRange: function() {
                var businessRanges = [],
                    series = this.series,
                    singleSeries = series[0],
                    range,
                    singleSeriesRange;
                this._disposeObjectsInArray("businessRanges");
                if (singleSeries) {
                    range = new charts.Range({series: singleSeries});
                    singleSeriesRange = singleSeries.getRangeData();
                    range = range.getBoundRange(singleSeriesRange);
                    if (!range.isDefined())
                        range.setStubData();
                    businessRanges.push(range)
                }
                this.businessRanges = businessRanges
            },
            _createTranslator: function(range, canvas) {
                return new DevExpress.viz.core.Translator1D(range.minY, range.maxY, 360, 0)
            },
            _populateSeries: function() {
                var _this = this,
                    renderer = _this.renderer,
                    hasSeriesTemplate = !!_this.option('seriesTemplate'),
                    seriesOptions = hasSeriesTemplate ? _this._templatedSeries : _this.option('series'),
                    allSeriesOptions = $.isArray(seriesOptions) ? seriesOptions : seriesOptions ? [seriesOptions] : [],
                    themeManager = _this.themeManager,
                    data,
                    particularSeriesOptions,
                    particularSeries,
                    seriesTheme,
                    seriesType,
                    commonSeriesSettings = _this.option('commonSeriesSettings'),
                    userCommonSeriesSettings = _this._userOptions.commonSeriesSettings,
                    incidentOccured = _this.option('incidentOccured');
                _this._disposeSeries();
                _this.series = [];
                themeManager.resetPalette();
                if (allSeriesOptions.length) {
                    particularSeriesOptions = allSeriesOptions[0];
                    if (particularSeriesOptions.type && !utils.isString(particularSeriesOptions.type))
                        particularSeriesOptions.type = '';
                    data = particularSeriesOptions.data;
                    particularSeriesOptions.data = null;
                    particularSeriesOptions.incidentOccured = incidentOccured;
                    seriesTheme = themeManager.applyPieSeriesTheme(particularSeriesOptions, commonSeriesSettings, userCommonSeriesSettings);
                    seriesTheme.seriesGroup = _this._seriesGroup;
                    seriesTheme.trackerGroup = _this._trackerGroup;
                    seriesTheme.seriesLabelsGroup = _this._labelsGroup;
                    seriesTheme.seriesTrackerGroup = _this._seriesTrackerGroup;
                    seriesTheme.markerTrackerGroup = _this._markerTrackerGroup;
                    seriesType = seriesTheme.type !== undefined ? seriesTheme.type : _this.option('commonSeriesSettings').type;
                    particularSeries = charts.factory.createSeries(seriesType, renderer, seriesTheme);
                    if (!particularSeries)
                        incidentOccured.call(null, 'Unknown series type requested: ' + seriesType);
                    else {
                        _this._processSingleSeries(particularSeries, particularSeries.userOptions);
                        _this.series.push(particularSeries)
                    }
                    particularSeriesOptions.data = data
                }
                return _this.series
            },
            _processSingleSeries: function(singleSeries, options) {
                var commonSeriesSettings = this.option('commonSeriesSettings'),
                    points,
                    seriesGroup = options.seriesGroup,
                    trackerGroup = options.trackerGroup,
                    seriesTrackerGroup = options.seriesTrackerGroup,
                    markerTrackerGroup = options.markerTrackerGroup,
                    seriesLabelsGroup = options.seriesLabelsGroup;
                singleSeries.arrangePoints();
                points = singleSeries && singleSeries.getPoints() || [];
                options.seriesGroup = null;
                options.trackerGroup = null;
                options.seriesTrackerGroup = null;
                options.markerTrackerGroup = null;
                options.seriesLabelsGroup = null;
                for (var j = 0; j < points.length; j++) {
                    var theme = this.themeManager.applyNextPieSegmentTheme(options, commonSeriesSettings);
                    var convertedTheme = singleSeries.parseStyleOptions(theme);
                    points[j].setOptions(convertedTheme.point);
                    points[j].index = j
                }
                options.seriesGroup = seriesGroup;
                options.trackerGroup = trackerGroup;
                options.seriesTrackerGroup = seriesTrackerGroup;
                options.markerTrackerGroup = markerTrackerGroup;
                options.seriesLabelsGroup = seriesLabelsGroup
            },
            _handleSeriesPopulated: function(needRedraw) {
                var _this = this;
                _this._populateBusinessRange();
                _this._createLegend();
                _this._updateTracker();
                needRedraw && _this._render({
                    force: true,
                    recreateCanvas: true
                })
            },
            _createLegend: function() {
                var _this = this,
                    legendOptions = $.extend(true, {
                        renderer: _this.renderer,
                        series: $.map(_this.series[0] ? _this.series[0].getPoints() : [], function(item) {
                            item.name = item.argument;
                            item.options.showInLegend = true,
                            item.styles = {themeColor: item.options.attributes.fill};
                            return item
                        })
                    }, _this.option('legend'));
                if (legendOptions.position !== 'outside')
                    legendOptions.position = 'outside';
                _this.legend = charts.factory.createLegend(legendOptions, _this._legendGroup, _this._legendTrackerGroup)
            },
            _render: function(drawOptions) {
                var _this = this,
                    titleOptions = _this.option('title'),
                    layoutManager = _this.layoutManager;
                drawOptions = _this._prepareDrawOptions(drawOptions);
                _this.callBase(drawOptions);
                if (_this.stopRedraw) {
                    _this.stopRedraw = false;
                    return
                }
                if (titleOptions.text && drawOptions.drawTitle) {
                    _this._titleGroup.append();
                    _this._drawTitle();
                    layoutManager.applyTitleLayout()
                }
                if (drawOptions.drawLegend && _this.legend) {
                    _this.legend.canvas = _this.canvas;
                    _this._legendGroup.append();
                    _this.legend.draw();
                    layoutManager.applyLegendLayout()
                }
                if (layoutManager.isCanvasExceeded(false)) {
                    _this.option('incidentOccured')('Container is too small to draw chart with current settings');
                    _this._clean();
                    return
                }
                if (_this.chartTitle)
                    _this.chartTitle.setClipRectSettings();
                if (_this.series && _this.series[0]) {
                    if (!layoutManager.applyPieChartSeriesLayout()) {
                        _this.option('incidentOccured')('Container is too small to draw chart with current settings');
                        _this._clean();
                        return
                    }
                    _this._seriesGroup.append();
                    _this._labelsGroup.append();
                    _this.series[0].canvas = _this.canvas;
                    _this.series[0].draw(_this._createTranslator(_this.businessRanges[0], _this.canvas), drawOptions.animate && _this.renderer.animationEnabled());
                    if (_this.series[0].redraw) {
                        _this._seriesGroup.detach();
                        _this._trackerGroup.detach();
                        _this._labelsGroup.detach();
                        _this._seriesGroup.clear();
                        _this._labelsGroup.clear();
                        _this._seriesGroup.append();
                        _this._labelsGroup.append();
                        layoutManager.applyPieChartSeriesLayout();
                        _this.series[0].draw(_this._createTranslator(_this.businessRanges[0], _this.canvas), drawOptions.animate && _this.renderer.animationEnabled())
                    }
                    _this._tooltipGroup.append();
                    _this._trackerGroup.append();
                    _this._createTooltip();
                    _this.series[0].drawTrackers();
                    _this.tracker._prepare('pieChart')
                }
                _this._handleRenderComplete()
            },
            getSeries: function getSeries() {
                return this.series && this.series[0]
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-charts, file layoutManager.js */
    (function($, DX, undefined) {
        var isNumber = DX.utils.isNumber,
            round = Math.round;
        DX.viz.charts.LayoutManager = DX.Class.inherit(function() {
            var update = function(chart) {
                    this.chart = chart;
                    setCanvasValues(chart && chart.canvas)
                };
            var dispose = function() {
                    this.chart = null
                };
            var setCanvasValues = function(canvas) {
                    if (canvas) {
                        canvas.originalTop = canvas.top;
                        canvas.originalBottom = canvas.bottom;
                        canvas.originalLeft = canvas.left;
                        canvas.originalRight = canvas.right
                    }
                };
            var createPanesCanvases = function(panesBorderOptions) {
                    var debug = DX.utils.debug;
                    $.each(this.chart.panes, function(i, item) {
                        debug.assert(item, 'pane is null object');
                        debug.assert(item.name, 'Pane does not have name')
                    });
                    var chart = this.chart,
                        canvas = chart.canvas,
                        panes = chart.panes,
                        pane,
                        i,
                        panesNumber = panes.length,
                        paneSpaceHeight = canvas.height - canvas.top - canvas.bottom,
                        paneSpaceWidth = canvas.width - canvas.left - canvas.right,
                        weightSum = 0,
                        oneWeightHeight,
                        oneWeightWidth,
                        padding = panes.padding || 10,
                        distributedTopSpace = 0,
                        INDENT = 10,
                        distributedLeftSpace = 0;
                    for (i = 0; i < panesNumber; i++) {
                        pane = panes[i];
                        pane.weight = pane.weight || 1;
                        weightSum = weightSum + pane.weight
                    }
                    oneWeightHeight = (paneSpaceHeight - padding * (panesNumber - 1)) / weightSum;
                    oneWeightWidth = (paneSpaceWidth - padding * (panesNumber - 1)) / weightSum;
                    if (!chart.option('rotated'))
                        for (i = 0; i < panesNumber; i++) {
                            pane = panes[i];
                            pane.calcHeight = round(pane.weight * oneWeightHeight);
                            pane.canvas = $.extend({}, canvas);
                            pane.canvas.top = pane.canvas.originalTop = canvas.top + distributedTopSpace;
                            pane.canvas.bottom = pane.canvas.originalBottom = canvas.bottom + (paneSpaceHeight - pane.calcHeight - distributedTopSpace);
                            if (!panesBorderOptions[pane.name].visible) {
                                pane.canvas.right += INDENT;
                                pane.canvas.left += INDENT;
                                pane.canvas.top += INDENT;
                                pane.canvas.bottom += INDENT
                            }
                            distributedTopSpace = distributedTopSpace + pane.calcHeight + padding
                        }
                    else
                        for (i = 0; i < panesNumber; i++) {
                            pane = panes[i];
                            pane.calcWidth = round(pane.weight * oneWeightWidth);
                            pane.canvas = $.extend({}, canvas);
                            pane.canvas.left = pane.canvas.originalLeft = canvas.left + distributedLeftSpace;
                            pane.canvas.right = pane.canvas.originalRight = canvas.right + (paneSpaceWidth - pane.calcWidth - distributedLeftSpace);
                            if (!panesBorderOptions[pane.name].visible) {
                                pane.canvas.top += INDENT;
                                pane.canvas.bottom += INDENT;
                                pane.canvas.right += INDENT;
                                pane.canvas.left += INDENT
                            }
                            distributedLeftSpace = distributedLeftSpace + pane.calcWidth + padding
                        }
                };
            var applyTitleLayout = function() {
                    var chart = this.chart,
                        canvas = chart.canvas,
                        title = chart.chartTitle,
                        box,
                        horizontalPadding = 15,
                        verticalPadding = 10,
                        shiftX,
                        shiftY;
                    if (!title)
                        return;
                    box = title.getBoundingRect();
                    switch (title.horizontalAlignment) {
                        case'left':
                            shiftX = round(horizontalPadding + canvas.left);
                            break;
                        case'center':
                            shiftX = round((canvas.width - canvas.left - canvas.right - box.width) / 2 + canvas.left) - box.x;
                            break;
                        case'right':
                            shiftX = round(canvas.width - canvas.right - box.x - box.width - horizontalPadding);
                            break
                    }
                    if (title.verticalAlignment === 'top') {
                        shiftY = round(canvas.top - box.y);
                        canvas.top = canvas.top + box.height + verticalPadding
                    }
                    else {
                        shiftY = round(canvas.height - canvas.bottom - box.height - box.y);
                        canvas.bottom = canvas.bottom + box.height + verticalPadding
                    }
                    title.shift(shiftX, shiftY);
                    setCanvasValues(canvas)
                };
            var adjustTitleLayout = function adjustTitleLayout() {
                    var chart = this.chart,
                        canvas = chart.canvas,
                        title = chart.chartTitle,
                        horizontalPadding = 15,
                        box,
                        shiftX,
                        shiftY = title.innerTitleGroup.settings.translateY || 0;
                    title.canvas = canvas;
                    title.correctTitleLength();
                    box = title.getBoundingRect();
                    switch (title.horizontalAlignment) {
                        case'left':
                            shiftX = round(horizontalPadding + canvas.left);
                            break;
                        case'center':
                            shiftX = round((canvas.width - canvas.right - canvas.left - box.width) / 2 + canvas.left - box.x);
                            break;
                        case'right':
                            shiftX = round(canvas.width - canvas.right - box.x - box.width - horizontalPadding);
                            break
                    }
                    title.shift(shiftX, shiftY)
                };
            var applyLegendLayout = function applyLegendLayout() {
                    var _this = this,
                        chart = _this.chart,
                        canvas = chart.canvas,
                        legend = chart.legend,
                        title = chart.chartTitle,
                        panes = chart.panes,
                        options = legend.options,
                        rect = legend.getBoundingRect(),
                        verticalPadding = 10,
                        horizontalPadding = 10,
                        shiftX,
                        shiftY;
                    if (!options.visible)
                        return;
                    if (!isNumber(rect.width) || !isNumber(rect.height))
                        return;
                    if (options.position === 'outside') {
                        switch (options.horizontalAlignment) {
                            case'left':
                                shiftX = round(canvas.left - rect.x + horizontalPadding);
                                canvas.left = canvas.left + rect.width + options.margin + horizontalPadding;
                                if (title)
                                    _this.adjustTitleLayout();
                                break;
                            case'center':
                                shiftX = round((canvas.width - canvas.left - canvas.right - rect.width) / 2 + canvas.left - rect.x);
                                break;
                            case'right':
                                shiftX = round(canvas.width - canvas.right - rect.width - rect.x - horizontalPadding);
                                canvas.right = canvas.right + rect.width + options.margin + horizontalPadding;
                                if (title)
                                    _this.adjustTitleLayout();
                                break
                        }
                        switch (options.verticalAlignment) {
                            case'top':
                                shiftY = round(verticalPadding + canvas.top - rect.y);
                                if (options.horizontalAlignment === 'center')
                                    canvas.top = canvas.top + rect.height + options.margin + verticalPadding;
                                break;
                            case'bottom':
                                shiftY = round(canvas.height - rect.height - canvas.bottom - verticalPadding - rect.y);
                                if (options.horizontalAlignment === 'center')
                                    canvas.bottom = canvas.bottom + rect.height + options.margin + verticalPadding;
                                break
                        }
                        legend.shift(shiftX, shiftY);
                        setCanvasValues(canvas)
                    }
                    else {
                        canvas = $.extend(true, {}, panes[0].canvas);
                        canvas.bottom = panes[panes.length - 1].canvas.bottom;
                        canvas.right = panes[panes.length - 1].canvas.right;
                        switch (options.horizontalAlignment) {
                            case'left':
                                shiftX = round(canvas.left - rect.x + options.margin);
                                break;
                            case'center':
                                shiftX = round((canvas.width - canvas.left - canvas.right - rect.width) / 2 + canvas.left - rect.x);
                                break;
                            case'right':
                                shiftX = round(canvas.width - canvas.right - rect.width - rect.x - options.margin);
                                break
                        }
                        switch (options.verticalAlignment) {
                            case'top':
                                shiftY = round(canvas.top - rect.y + options.margin);
                                break;
                            case'bottom':
                                shiftY = round(canvas.height - rect.height - canvas.bottom - options.margin - rect.y);
                                break
                        }
                        legend.shift(shiftX, shiftY)
                    }
                };
            var applyPieChartSeriesLayout = function() {
                    var chart = this.chart,
                        canvas = chart.canvas,
                        singleSeries = chart.series[0] || {},
                        paneSpaceHeight = canvas.height - canvas.top - canvas.bottom,
                        paneSpaceWidth = canvas.width - canvas.left - canvas.right,
                        min = paneSpaceWidth < paneSpaceHeight ? paneSpaceWidth : paneSpaceHeight,
                        accessibleRadius,
                        outerRadius = singleSeries.outerRadius,
                        innerRadius = singleSeries.type === 'pie' ? 0 : singleSeries.innerRadius || 0;
                    if (!(singleSeries && singleSeries.correctPosition))
                        return;
                    if (singleSeries.type !== 'pie')
                        if (!isNumber(innerRadius))
                            innerRadius = 0.5;
                        else {
                            innerRadius = Number(innerRadius);
                            if (innerRadius < 0.2)
                                innerRadius = 0.2;
                            if (innerRadius > 0.8)
                                innerRadius = 0.8
                        }
                    if (min < singleSeries.labelSpace)
                        return false;
                    accessibleRadius = outerRadius || (min - singleSeries.labelSpace - singleSeries.hoverSpace) / 2;
                    singleSeries.correctPosition({
                        centerX: round(paneSpaceWidth / 2 + canvas.left),
                        centerY: round(paneSpaceHeight / 2 + canvas.top),
                        radiusInner: round(accessibleRadius * innerRadius),
                        radiusOuter: round(accessibleRadius)
                    });
                    return true
                };
            var isValidBox = function isValidBox(box) {
                    return !!(box.x || box.y || box.width || box.height)
                };
            var correctDeltaMarginValue = function(panes, canvasesGrid, marginSides) {
                    var axisPanePosition,
                        canvasCell,
                        canvas,
                        deltaSide,
                        requireAxesRedraw;
                    $.each(panes, function(_, pane) {
                        axisPanePosition = getPanePosition(canvasesGrid, pane.name);
                        canvasCell = canvasesGrid[axisPanePosition.row][axisPanePosition.col];
                        canvas = canvasCell.canvas;
                        $.each(marginSides, function(_, side) {
                            deltaSide = 'delta' + side;
                            canvasCell[deltaSide] = Math.max(canvasCell[deltaSide] - (canvas[side.toLowerCase()] - canvas['original' + side]), 0);
                            if (canvasCell[deltaSide] > 0)
                                requireAxesRedraw = true
                        })
                    });
                    return requireAxesRedraw
                };
            var applyVerticalAxesLayout = function() {
                    var _this = this,
                        chart = _this.chart,
                        axes = chart.verticalAxes,
                        canvas,
                        axisPanePosition,
                        axisPosition,
                        canvasesGrid,
                        canvasCell,
                        box,
                        delta,
                        axis,
                        axisWidth,
                        commonAxisWidht = 0,
                        direction,
                        directionMultiplier,
                        i;
                    canvasesGrid = distributeCanvases(_this, chart.panes);
                    for (i = 0; i < axes.length; i++) {
                        axis = axes[i];
                        axisPosition = axis.options.position || 'left';
                        axis.delta = {};
                        box = axis.getBoundingRect();
                        if (!isValidBox(box))
                            continue;
                        axisPanePosition = getPanePosition(canvasesGrid, axes[i].pane);
                        canvasCell = canvasesGrid[axisPanePosition.row][axisPanePosition.col];
                        canvas = canvasCell.canvas;
                        if (axisPosition == 'right') {
                            direction = 'deltaRight';
                            directionMultiplier = 1;
                            canvasCell['deltaLeft'] += axis.padding && axis.padding['left']
                        }
                        else {
                            direction = 'deltaLeft';
                            directionMultiplier = -1;
                            canvasCell['deltaRight'] += axis.padding && axis.padding['right']
                        }
                        axisWidth = box.width;
                        if (!axis.delta[axisPosition] && canvasCell[direction] > 0)
                            canvasCell[direction] += axes[i].getMultipleAxesSpacing();
                        axes[i].delta[axisPosition] = axes[i].delta[axisPosition] || 0;
                        axes[i].delta[axisPosition] += canvasCell[direction] * directionMultiplier;
                        canvasCell[direction] += axisWidth;
                        delta = box.y + box.height - (canvas.height - canvas.originalBottom);
                        if (delta > 0) {
                            _this.requireAxesRedraw = true;
                            canvasCell.deltaBottom += delta
                        }
                        delta = canvas.originalTop - box.y;
                        if (delta > 0) {
                            _this.requireAxesRedraw = true;
                            canvasCell.deltaTop += delta
                        }
                    }
                    _this.requireAxesRedraw = correctDeltaMarginValue(chart.panes, canvasesGrid, ['Left', 'Right']) || _this.requireAxesRedraw;
                    applyFoundExceedings(canvasesGrid)
                };
            var applyHorizontalAxesLayout = function() {
                    var _this = this,
                        chart = _this.chart,
                        panes = chart.panes,
                        axes = chart.horizontalAxes,
                        canvas,
                        axisPanePosition,
                        canvasesGrid,
                        canvasCell,
                        box,
                        delta,
                        axis,
                        axisHeight,
                        direction,
                        directionMultiplier,
                        axisPosition,
                        i;
                    canvasesGrid = distributeCanvases(_this, panes);
                    for (i = axes.length - 1; i >= 0; i--) {
                        axis = axes[i];
                        axisPosition = axis.options.position || 'bottom';
                        axes[i].delta = {};
                        box = axes[i].getBoundingRect();
                        if (!isValidBox(box))
                            continue;
                        axisPanePosition = getPanePosition(canvasesGrid, axes[i].pane);
                        canvasCell = canvasesGrid[axisPanePosition.row][axisPanePosition.col];
                        canvas = canvasCell.canvas;
                        if (axisPosition == 'top') {
                            direction = 'deltaTop';
                            directionMultiplier = -1;
                            canvasCell['deltaBottom'] += axis.padding && axis.padding['bottom']
                        }
                        else {
                            direction = 'deltaBottom';
                            directionMultiplier = 1;
                            canvasCell['deltaTop'] += axis.padding && axis.padding['top']
                        }
                        axisHeight = box.height;
                        if (!axis.delta[axisPosition] && canvasCell[direction] > 0)
                            canvasCell[direction] += axes[i].getMultipleAxesSpacing();
                        axes[i].delta[axisPosition] = axes[i].delta[axisPosition] || 0;
                        axes[i].delta[axisPosition] += canvasCell[direction] * directionMultiplier;
                        canvasCell[direction] += axisHeight;
                        delta = canvas.originalLeft - box.x;
                        if (delta > 0) {
                            _this.requireAxesRedraw = true;
                            canvasCell.deltaLeft += delta
                        }
                        delta = box.x + box.width - (canvas.width - canvas.originalRight);
                        if (delta > 0) {
                            _this.requireAxesRedraw = true;
                            canvasCell.deltaRight = delta
                        }
                    }
                    _this.requireAxesRedraw = correctDeltaMarginValue(panes, canvasesGrid, ['Bottom', 'Top']) || _this.requireAxesRedraw;
                    applyFoundExceedings(canvasesGrid)
                };
            var distributeCanvases = function distributeCanvases(_this, panes) {
                    var panesLength = panes.length,
                        i,
                        j,
                        canvasesGrid = [],
                        canvasesRow = [],
                        rotated = _this.chart.option('rotated');
                    for (i = 0; i < panesLength; i++) {
                        if (!rotated)
                            canvasesRow = [];
                        canvasesRow.push({
                            canvas: panes[i].canvas,
                            pane: panes[i].name,
                            deltaLeft: 0,
                            deltaRight: 0,
                            deltaTop: 0,
                            deltaBottom: 0
                        });
                        !rotated && canvasesGrid.push(canvasesRow)
                    }
                    rotated && canvasesGrid.push(canvasesRow);
                    return canvasesGrid
                };
            var getPanePosition = function getPanePosition(canvasesGrid, pane) {
                    var row,
                        col;
                    for (row = 0; row < canvasesGrid.length; row++)
                        for (col = 0; col < canvasesGrid[row].length; col++)
                            if (canvasesGrid[row][col].pane === pane)
                                return {
                                        row: row,
                                        col: col
                                    }
                };
            var changeRowCanvas = function changeRowCanvas(canvasesGrid, row, callback) {
                    var col;
                    for (col = 0; col < canvasesGrid[row].length; col++)
                        callback(canvasesGrid[row][col].canvas)
                };
            var changeColumnCanvas = function changeRowCanvas(canvasesGrid, col, callback) {
                    var row;
                    for (row = 0; row < canvasesGrid.length; row++)
                        callback(canvasesGrid[row][col].canvas)
                };
            var applyFoundExceedings = function applyFoundExceedings(canvasesGrid) {
                    var col,
                        row,
                        canvasesRow,
                        maxLeft = 0,
                        maxRight = 0,
                        maxTop = 0,
                        maxBottom = 0,
                        maxColNumber = 0;
                    for (row = 0; row < canvasesGrid.length; row++) {
                        maxTop = 0;
                        maxBottom = 0;
                        canvasesRow = canvasesGrid[row];
                        if (canvasesRow.length > maxColNumber)
                            maxColNumber = canvasesRow.length;
                        for (col = 0; col < canvasesRow.length; col++) {
                            if (canvasesRow[col] && canvasesRow[col].deltaTop > maxTop)
                                maxTop = canvasesRow[col].deltaTop;
                            if (canvasesRow[col] && canvasesRow[col].deltaBottom > maxBottom)
                                maxBottom = canvasesRow[col].deltaBottom
                        }
                        if (maxTop)
                            changeRowCanvas(canvasesGrid, row, function(canvas) {
                                canvas.top += maxTop
                            });
                        if (maxBottom)
                            changeRowCanvas(canvasesGrid, row, function(canvas) {
                                canvas.bottom += maxBottom
                            })
                    }
                    for (col = 0; col < maxColNumber; col++) {
                        maxLeft = 0;
                        maxRight = 0;
                        for (row = 0; row < canvasesGrid.length; row++) {
                            canvasesRow = canvasesGrid[row];
                            if (canvasesRow[col] && canvasesRow[col].deltaLeft > maxLeft)
                                maxLeft = canvasesRow[col].deltaLeft;
                            if (canvasesRow[col] && canvasesRow[col].deltaRight > maxRight)
                                maxRight = canvasesRow[col].deltaRight
                        }
                        if (maxLeft)
                            changeColumnCanvas(canvasesGrid, col, function(canvas) {
                                canvas.left += maxLeft
                            });
                        if (maxRight)
                            changeColumnCanvas(canvasesGrid, col, function(canvas) {
                                canvas.right += maxRight
                            })
                    }
                };
            var isSingleCanvasExceeded = function isSingleCanvasExceeded(canvas) {
                    if (canvas.left > canvas.width - canvas.right || canvas.right > canvas.width - canvas.left || canvas.top > canvas.height - canvas.bottom || canvas.bottom > canvas.height - canvas.top)
                        return true
                };
            var isCanvasExceeded = function isCanvasExceeded(includePanes) {
                    var chart = this.chart,
                        paneCanvasesExceed = false;
                    if (isSingleCanvasExceeded(chart.canvas))
                        return true;
                    if (includePanes)
                        $.each(chart && chart.panes || {}, function(_, pane) {
                            if (pane.canvas && isSingleCanvasExceeded(pane.canvas)) {
                                paneCanvasesExceed = true;
                                return false
                            }
                        });
                    return paneCanvasesExceed
                };
            return {
                    update: update,
                    createPanesCanvases: createPanesCanvases,
                    applyLegendLayout: applyLegendLayout,
                    applyTitleLayout: applyTitleLayout,
                    adjustTitleLayout: adjustTitleLayout,
                    applyVerticalAxesLayout: applyVerticalAxesLayout,
                    applyHorizontalAxesLayout: applyHorizontalAxesLayout,
                    applyPieChartSeriesLayout: applyPieChartSeriesLayout,
                    isCanvasExceeded: isCanvasExceeded,
                    dispose: dispose
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-charts, file multiAxesSynchronizer.js */
    (function($, DX, undefined) {
        var charts = DX.viz.charts,
            utils = DX.utils,
            math = Math;
        charts.MultiAxesSynchronizer = DX.Class.inherit(function() {
            var getValueAxesPerPanes = function(valueAxes) {
                    var result = {};
                    $.each(valueAxes, function() {
                        if (!result[this.pane])
                            result[this.pane] = [];
                        result[this.pane].push(this)
                    });
                    return result
                };
            var restoreOriginalBusinessRange = function(axis) {
                    var businessRange;
                    if (!axis.translator._originalBusinessRange)
                        axis.translator._originalBusinessRange = new charts.Range(axis.translator.getBusinessRange());
                    else {
                        businessRange = new charts.Range(axis.translator._originalBusinessRange);
                        axis.translator.updateBusinessRange(businessRange);
                        axis.setRange(businessRange)
                    }
                };
            var linearConvertor = {
                    transform: function(v, b) {
                        return utils.getLog(v, b)
                    },
                    addInterval: function(v, i) {
                        return v + i
                    },
                    getInterval: function(base, tickInterval) {
                        return tickInterval
                    },
                    adjustValue: math.floor
                };
            var logConvertor = {
                    transform: function(v, b) {
                        return utils.raiseTo(v, b)
                    },
                    addInterval: function(v, i) {
                        return v * i
                    },
                    getInterval: function(base, tickInterval) {
                        return math.pow(base, tickInterval)
                    },
                    adjustValue: utils.adjustValue
                };
            var convertAxisInfo = function(axisInfo, convertor) {
                    if (!axisInfo.isLogarithmic)
                        return;
                    var base = axisInfo.logarithmicBase,
                        tickValues = axisInfo.tickValues,
                        tick,
                        ticks = [],
                        interval;
                    axisInfo.minValue = convertor.transform(axisInfo.minValue, base);
                    axisInfo.oldMinValue = convertor.transform(axisInfo.oldMinValue, base);
                    axisInfo.maxValue = convertor.transform(axisInfo.maxValue, base);
                    axisInfo.oldMaxValue = convertor.transform(axisInfo.oldMaxValue, base);
                    axisInfo.tickInterval = math.round(axisInfo.tickInterval);
                    if (axisInfo.tickInterval < 1)
                        axisInfo.tickInterval = 1;
                    interval = convertor.getInterval(base, axisInfo.tickInterval);
                    for (tick = convertor.adjustValue(convertor.transform(axisInfo.tickValues[0], base)); ticks.length < axisInfo.tickValues.length; tick = convertor.addInterval(tick, interval))
                        ticks.push(tick);
                    ticks.tickInterval = axisInfo.tickInterval;
                    axisInfo.tickValues = ticks
                };
            var populateAxesInfo = function(axes, rotated) {
                    var axesInfo = [];
                    $.each(axes, function() {
                        var tickValues,
                            minValue,
                            maxValue,
                            inverted,
                            axisInfo,
                            businessRange,
                            logarithmicBase,
                            stubData = rotated && 'stubDataX' || 'stubDataY';
                        restoreOriginalBusinessRange(this);
                        tickValues = this.getTickValues();
                        if (tickValues && tickValues.length > 0 && utils.isNumber(tickValues[0]) && this.options.type !== 'discrete') {
                            businessRange = this.translator.getBusinessRange();
                            minValue = rotated ? businessRange.minVisibleX : businessRange.minVisibleY;
                            maxValue = rotated ? businessRange.maxVisibleX : businessRange.maxVisibleY;
                            inverted = rotated ? businessRange.invertX : businessRange.invertY;
                            logarithmicBase = rotated ? businessRange.baseX : businessRange.baseY;
                            axisInfo = {
                                axis: this,
                                isLogarithmic: this.options.type === 'logarithmic',
                                logarithmicBase: logarithmicBase,
                                tickValues: tickValues,
                                minValue: minValue,
                                oldMinValue: minValue,
                                maxValue: maxValue,
                                oldMaxValue: maxValue,
                                inverted: inverted,
                                tickInterval: tickValues.tickInterval,
                                synchronizedValue: this.options.synchronizedValue
                            };
                            if (businessRange[stubData]) {
                                axisInfo.stubData = true;
                                axisInfo.tickInterval = axisInfo.axis.options.tickInterval;
                                axisInfo.isLogarithmic = false
                            }
                            convertAxisInfo(axisInfo, linearConvertor);
                            if (!axisInfo.tickInterval && tickValues.length > 1)
                                axisInfo.tickInterval = tickValues[1] - tickValues[0];
                            axesInfo.push(axisInfo)
                        }
                    });
                    return axesInfo
                };
            var updateTickValues = function(axesInfo) {
                    var maxTicksCount = 0,
                        ticksMultiplier,
                        ticksCount,
                        additionalStartTicksCount = 0;
                    $.each(axesInfo, function() {
                        maxTicksCount = math.max(maxTicksCount, this.tickValues.length)
                    });
                    $.each(axesInfo, function() {
                        if (utils.isDefined(this.synchronizedValue)) {
                            this.baseTickValue = this.synchronizedValue;
                            this.invertedBaseTickValue = this.synchronizedValue;
                            this.tickValues = [this.baseTickValue]
                        }
                        else {
                            if (this.tickValues.length > 1 && this.tickInterval) {
                                ticksMultiplier = math.floor((maxTicksCount + 1) / this.tickValues.length);
                                ticksCount = ticksMultiplier > 1 ? math.floor((maxTicksCount + 1) / ticksMultiplier) : maxTicksCount;
                                additionalStartTicksCount = math.floor((ticksCount - this.tickValues.length) / 2);
                                while (additionalStartTicksCount > 0 && this.tickValues[0] !== 0) {
                                    this.tickValues.unshift(utils.adjustValue(this.tickValues[0] - this.tickInterval));
                                    additionalStartTicksCount--
                                }
                                while (this.tickValues.length < ticksCount)
                                    this.tickValues.push(utils.adjustValue(this.tickValues[this.tickValues.length - 1] + this.tickInterval));
                                this.tickInterval = this.tickInterval / ticksMultiplier
                            }
                            this.baseTickValue = this.tickValues[0];
                            this.invertedBaseTickValue = this.tickValues[this.tickValues.length - 1]
                        }
                    })
                };
            var getAxisRange = function(axisInfo) {
                    return axisInfo.maxValue - axisInfo.minValue
                };
            var getMainAxisInfo = function(axesInfo) {
                    var i;
                    for (i = 0; i < axesInfo.length; i++)
                        if (!axesInfo[i].stubData)
                            return axesInfo[i];
                    return null
                };
            var correctMinMaxValues = function(axesInfo) {
                    var mainAxisInfo = getMainAxisInfo(axesInfo);
                    $.each(axesInfo, function() {
                        var scale,
                            move,
                            mainAxisBaseValueOffset;
                        if (this !== mainAxisInfo) {
                            if (mainAxisInfo.tickInterval && this.tickInterval) {
                                if (this.stubData && utils.isDefined(this.synchronizedValue)) {
                                    this.oldMinValue = this.minValue = this.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.minValue) / mainAxisInfo.tickInterval * this.tickInterval;
                                    this.oldMaxValue = this.maxValue = this.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.maxValue) / mainAxisInfo.tickInterval * this.tickInterval;
                                    this.stubData = false
                                }
                                scale = mainAxisInfo.tickInterval / getAxisRange(mainAxisInfo) / this.tickInterval * getAxisRange(this);
                                this.maxValue = this.minValue + getAxisRange(this) / scale
                            }
                            if (mainAxisInfo.inverted && !this.inverted || !mainAxisInfo.inverted && this.inverted)
                                mainAxisBaseValueOffset = mainAxisInfo.maxValue - mainAxisInfo.invertedBaseTickValue;
                            else
                                mainAxisBaseValueOffset = mainAxisInfo.baseTickValue - mainAxisInfo.minValue;
                            move = (mainAxisBaseValueOffset / getAxisRange(mainAxisInfo) - (this.baseTickValue - this.minValue) / getAxisRange(this)) * getAxisRange(this);
                            this.minValue -= move;
                            this.maxValue -= move
                        }
                    })
                };
            var calculatePaddings = function(axesInfo) {
                    var minPadding,
                        maxPadding,
                        startPadding = 0,
                        endPadding = 0;
                    $.each(axesInfo, function() {
                        minPadding = this.minValue > this.oldMinValue ? (this.minValue - this.oldMinValue) / getAxisRange(this) : 0;
                        maxPadding = this.maxValue < this.oldMaxValue ? (this.oldMaxValue - this.maxValue) / getAxisRange(this) : 0;
                        if (this.inverted) {
                            startPadding = math.max(startPadding, maxPadding);
                            endPadding = math.max(endPadding, minPadding)
                        }
                        else {
                            startPadding = math.max(startPadding, minPadding);
                            endPadding = math.max(endPadding, maxPadding)
                        }
                    });
                    return {
                            start: startPadding,
                            end: endPadding
                        }
                };
            var correctMinMaxValuesByPaddings = function(axesInfo, paddings) {
                    var range;
                    $.each(axesInfo, function() {
                        range = getAxisRange(this);
                        if (this.inverted) {
                            this.minValue -= paddings.end * range;
                            this.maxValue += paddings.start * range
                        }
                        else {
                            this.minValue -= paddings.start * range;
                            this.maxValue += paddings.end * range
                        }
                        this.minValue = math.min(this.minValue, utils.adjustValue(this.minValue));
                        this.maxValue = math.max(this.maxValue, utils.adjustValue(this.maxValue))
                    })
                };
            var updateTickValuesIfSyncronizedValueUsed = function(axesInfo) {
                    var hasSyncronizedValue = false;
                    $.each(axesInfo, function() {
                        hasSyncronizedValue = hasSyncronizedValue || utils.isDefined(this.synchronizedValue)
                    });
                    $.each(axesInfo, function() {
                        var lastTickValue;
                        if (hasSyncronizedValue && this.tickInterval) {
                            while (this.tickValues[0] - this.tickInterval >= this.minValue)
                                this.tickValues.unshift(utils.adjustValue(this.tickValues[0] - this.tickInterval));
                            lastTickValue = this.tickValues[this.tickValues.length - 1];
                            while ((lastTickValue = lastTickValue + this.tickInterval) <= this.maxValue)
                                this.tickValues.push(utils.adjustValue(lastTickValue))
                        }
                        while (this.tickValues[0] < this.minValue)
                            this.tickValues.shift();
                        while (this.tickValues[this.tickValues.length - 1] > this.maxValue)
                            this.tickValues.pop()
                    })
                };
            var applyMinMaxValues = function(axesInfo, rotated) {
                    var axis,
                        range,
                        stubData = rotated && 'stubDataX' || 'stubDataY';
                    $.each(axesInfo, function() {
                        axis = this.axis;
                        range = axis.translator.getBusinessRange();
                        if (rotated) {
                            if (range.minX === range.minVisibleX)
                                range.minX = this.minValue;
                            if (range.maxX === range.maxVisibleX)
                                range.maxX = this.maxValue;
                            range.minVisibleX = this.minValue;
                            range.maxVisibleX = this.maxValue
                        }
                        else {
                            if (range.minY === range.minVisibleY)
                                range.minY = this.minValue;
                            if (range.maxY === range.maxVisibleY)
                                range.maxY = this.maxValue;
                            range.minVisibleY = this.minValue;
                            range.maxVisibleY = this.maxValue
                        }
                        if (utils.isDefined(this.stubData))
                            range[stubData] = this.stubData;
                        if (range.minY > range.minVisibleY)
                            range.minY = range.minVisibleY;
                        if (range.maxY < range.maxVisibleY)
                            range.maxY = range.maxVisibleY;
                        if (range.minX > range.minVisibleX)
                            range.minX = range.minVisibleX;
                        if (range.maxX < range.maxVisibleX)
                            range.maxX = range.maxVisibleX;
                        axis.translator.updateBusinessRange(range);
                        axis.setRange(range);
                        axis.setTickValues(this.tickValues)
                    })
                };
            return {synchronize: function(valueAxes, rotated) {
                        var valueAxesPerPanes;
                        valueAxesPerPanes = getValueAxesPerPanes(valueAxes);
                        $.each(valueAxesPerPanes, function(i, axes) {
                            var axesInfo,
                                paddings;
                            if (axes.length > 1) {
                                axesInfo = populateAxesInfo(axes, rotated);
                                if (axesInfo.length === 0 || !getMainAxisInfo(axesInfo))
                                    return;
                                updateTickValues(axesInfo);
                                correctMinMaxValues(axesInfo);
                                paddings = calculatePaddings(axesInfo);
                                correctMinMaxValuesByPaddings(axesInfo, paddings);
                                updateTickValuesIfSyncronizedValueUsed(axesInfo);
                                $.each(axesInfo, function() {
                                    convertAxisInfo(this, logConvertor)
                                });
                                applyMinMaxValues(axesInfo, rotated)
                            }
                        })
                    }}
        }())
    })(jQuery, DevExpress);
    /*! Module viz-charts, file tracker.js */
    (function($, DX) {
        var charts = DX.viz.charts,
            eventsConsts = charts.series.consts.events,
            utils = DX.utils,
            isFunction = utils.isFunction,
            isDefined = utils.isDefined,
            MULTIPLE_MODE = 'multiple',
            SINGLE_MODE = 'single',
            ALL_ARGUMENTS_POINTS_MODE = 'allargumentpoints',
            ALL_SERIES_POINTS_MODE = 'allseriespoints',
            msPointerEnabled = window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints || window.navigator.pointerEnabled && window.navigator.maxTouchPoints || null,
            MOUSE_EVENT_LOCK_TIMEOUT = 1000,
            CLICK_EVENT_LOCK_TIMEOUT = 600,
            TOOLTIP_HOLD_TIMEOUT = 400,
            NONE_MODE = 'none';
        charts.Tracker = DX.Class.inherit({
            ctor: function(options) {
                var _this = this,
                    events = options.events = options.events || {},
                    getEventHandler = function(func) {
                        return func && func.call ? func : null
                    };
                _this._reinit(options);
                _this.pointSelectionMode = _this._prepareMode(options.pointSelectionMode);
                _this.seriesSelectionMode = _this._prepareMode(options.seriesSelectionMode);
                _this.hoverStartDelay = 100;
                _this.hoverHoldDelay = 200;
                _this.sensitivity = 7;
                if (_this.pointSelectionMode === MULTIPLE_MODE) {
                    _this._releaseSelectedPoint = _this._releaseSelectedPointMultiMode;
                    _this.selectedPoint = []
                }
                else
                    _this._releaseSelectedPoint = _this._releaseSelectedPointSingleMode;
                if (_this.seriesSelectionMode === MULTIPLE_MODE) {
                    _this._releaseSelectedSeries = _this._releaseSelectedSeriesMultiMode;
                    _this.selectedSeries = []
                }
                else
                    _this._releaseSelectedSeries = _this._releaseSelectedSeriesSingleMode;
                _this.tooltipEnabled = options.tooltipEnabled;
                _this.tooltipShown = options.tooltipShown;
                _this.tooltipHidden = options.tooltipHidden;
                _this.seriesClick = getEventHandler(events.seriesClick);
                _this.pointClick = getEventHandler(events.pointClick);
                _this.legendClick = getEventHandler(events.legendClick);
                _this.argumentAxisClick = getEventHandler(events.argumentAxisClick);
                _this.seriesHover = getEventHandler(events.seriesHover);
                _this.seriesSelected = getEventHandler(events.seriesSelected);
                _this.pointHover = getEventHandler(events.pointHover);
                _this.seriesSelectionChanged = getEventHandler(events.seriesSelectionChanged);
                _this.pointSelectionChanged = getEventHandler(events.pointSelectionChanged);
                _this.seriesHoverChanged = getEventHandler(events.seriesHoverChanged);
                _this.pointHoverChanged = getEventHandler(events.pointHoverChanged);
                _this.pointSelected = getEventHandler(events.pointSelected);
                _this.renderer = options.renderer;
                _this.seriesTrackerGroup = options.seriesTrackerGroup;
                _this.markerTrackerGroup = options.markerTrackerGroup;
                _this.seriesGroup = options.seriesGroup;
                _this.legendGroup = options.legendGroup;
                _this.seriesGroup.on(eventsConsts.selectSeries, {tracker: _this}, _this._selectSeries);
                _this.seriesGroup.on(eventsConsts.deselectSeries, {tracker: _this}, _this._deselectSeries);
                _this.seriesGroup.on(eventsConsts.selectPoint, {tracker: _this}, _this._selectPoint);
                _this.seriesGroup.on(eventsConsts.deselectPoint, {tracker: _this}, _this._deselectPoint);
                _this.seriesGroup.on(eventsConsts.showPointTooltip, {tracker: _this}, _this._showPointTooltip);
                _this.seriesGroup.on(eventsConsts.hidePointTooltip, {tracker: _this}, _this._hidePointTooltip);
                _this.crossHairOptions = options.crossHairOptions
            },
            _clean: function() {
                var _this = this;
                _this.selectedPoint = _this.pointSelectionMode === MULTIPLE_MODE ? [] : null;
                _this.selectedSeries = _this.seriesSelectionMode === MULTIPLE_MODE ? [] : null;
                _this.hoveredPoint = null;
                _this.hoveredSeries = null;
                _this._hideTooltip(_this.pointAtShownTooltip);
                clearTimeout(_this.tooltipHoldTimeout);
                clearTimeout(_this.hoverStartTimeOut);
                clearTimeout(_this.hoverHoldTimeOut)
            },
            _reinit: function(options) {
                options = options || {};
                this.storedSeries = options.series || [];
                this.argumentAxis = options.argumentAxis || [];
                this._clean()
            },
            dispose: function() {
                var _this = this;
                clearTimeout(_this.tooltipHoldTimeout);
                clearTimeout(_this.hoverStartTimeOut);
                clearTimeout(_this.hoverHoldTimeOut);
                clearTimeout(_this.unlockMouseTimer);
                clearTimeout(_this.lockClickTimer);
                $.each(_this.argumentAxis, function(_, axis) {
                    axis._axisElementsGroup && axis._axisElementsGroup.off()
                });
                _this.seriesTrackerGroup.off();
                _this.markerTrackerGroup.off();
                _this.legendGroup.off();
                _this.seriesGroup.off();
                _this.rootTracker && _this.rootTracker.off();
                _this.argumentAxis = null;
                _this.seriesTrackerGroup = null;
                _this.markerTrackerGroup = null;
                _this.legendGroup = null;
                _this.seriesGroup = null;
                _this.crossHairOptions = null;
                _this.selectedPoint = null;
                _this.selectedSeries = null;
                _this.hoveredSeries = null;
                _this.hoveredPoint = null;
                _this.storedSeries = null;
                _this.argumentAxis = null;
                _this.hoveredObject = null;
                _this.pointAtShownTooltip = null
            },
            _prepareMode: function(mode) {
                mode = (mode || '').toLowerCase();
                return mode = mode !== SINGLE_MODE && mode !== MULTIPLE_MODE ? SINGLE_MODE : mode
            },
            _prepare: function(typeChart) {
                var _this = this;
                _this.rootTracker = _this.renderer.getRoot();
                $.each(_this.argumentAxis, function(_, axis) {
                    _this._eventHandler(axis._axisElementsGroup, {
                        parser: _this._getOptionsAxis,
                        condition: _this._axisCondition,
                        execute: _this._axisEvent
                    }, {
                        tracker: _this,
                        axis: axis
                    })
                });
                _this._eventHandler(_this.seriesTrackerGroup, {
                    parser: _this._getOptionsPointSeries,
                    condition: _this._seriesCondition,
                    execute: _this._seriesEvent
                }, {tracker: _this});
                _this._eventHandler(_this.markerTrackerGroup, {
                    parser: _this._getOptionsPointSeries,
                    condition: _this._pointCondition,
                    execute: _this._pointEvent
                }, {tracker: _this});
                _this._eventHandler(_this.legendGroup, {
                    parser: _this._getOptionsPointSeries,
                    condition: _this._getLegendCondition(typeChart),
                    execute: _this._getLegendEvent(typeChart)
                }, {tracker: _this});
                _this._eventHandler(_this.rootTracker, {
                    parser: _this._getOptionsCrossHair,
                    execute: _this._crossHairEvent
                }, {tracker: _this})
            },
            _getLegendCondition: function(typeChart) {
                var legendCondition;
                if (typeChart === 'pieChart')
                    legendCondition = this._pointCondition;
                else
                    legendCondition = this._seriesCondition;
                this.__legendCondition = legendCondition;
                return legendCondition
            },
            _getLegendEvent: function(typeChart) {
                var self = this,
                    legendEvent;
                if (typeChart === 'pieChart')
                    legendEvent = $.extend({}, this._pointEvent, {
                        touchend: function(self, point, mode, event) {
                            if (!self.showHoldTooltip)
                                self._legendClick(self, point, true, event) || self._pointClick(self, point, true, event);
                            clearTimeout(self.tooltipHoldTimeout);
                            self._clickLock(self);
                            self._clearHover(self)
                        },
                        click: function(self, point, mode, event) {
                            self._legendClick(self, point, false, event) || self._pointClick(self, point, false, event);
                            self._clickLock(self)
                        }
                    });
                else
                    legendEvent = $.extend({}, this._seriesEvent, {
                        click: function(self, series, mode, event) {
                            self._legendClick(self, series, false, event) || self._seriesClick(self, series, false, event);
                            self._clickLock(self)
                        },
                        touchend: function(self, series, mode, event) {
                            self._legendClick(self, series, true, event) || self._seriesClick(self, series, true, event);
                            self._clickLock(self)
                        }
                    });
                this.__legendEvent = legendEvent;
                return legendEvent
            },
            _eventHandler: function(group, handlers, data) {
                var prepareHandlers = this._designerHandlers(handlers);
                group.off(".dxc-tracker");
                group.on(prepareHandlers, data)
            },
            _designerHandlers: function(handler) {
                var handlers = {},
                    parser = handler.parser,
                    condition = handler.condition,
                    execute = handler.execute,
                    designerHandle = function(eventType, func) {
                        if (condition && condition[eventType] === null)
                            return;
                        handlers[eventType + ".dxc-tracker"] = function(event) {
                            var options = parser ? parser(event) : event;
                            if (!options)
                                return;
                            if (condition && condition[eventType] && condition[eventType].call)
                                condition[eventType].apply(null, options.concat([func]));
                            else
                                func.apply(null, options)
                        }
                    };
                $.each(execute, designerHandle);
                return handlers
            },
            _getOptionsCrossHair: function(event) {
                var self = event.data.tracker;
                var rootOffset = utils.getRootOffset(self.renderer);
                var xe = event.pageX - rootOffset.left;
                var ye = event.pageY - rootOffset.top;
                return [self, xe, ye]
            },
            _getOptionsPointSeries: function(event) {
                var object = $(event.target).data('point') || $(event.target).data('series'),
                    self = event.data.tracker,
                    mode = object && ($(event.target).data('mode') || object.options.hoverMode);
                if (event.type === 'mousemove')
                    return [self, event.pageX, event.pageY, event.offsetX, event.offsetY];
                if (!object)
                    return null;
                return [self, object, mode, event]
            },
            _getOptionsAxis: function(event) {
                var self = event.data.tracker,
                    axis = event.data.axis,
                    mode = axis.options.hoverMode,
                    argument;
                if (event.target.tagName === "tspan")
                    argument = $(event.target).parent().data('argument');
                else
                    argument = $(event.target).data('argument');
                if (event.type === 'mousemove')
                    return [self, event.pageX, event.pageY];
                if (!axis)
                    return null;
                return [self, axis, mode, argument, event]
            },
            _pointEvent: {
                mouseover: function(self, point, mode) {
                    if (self.mouseLocked)
                        return;
                    self._setHoveredPoint(point, mode);
                    if (self.tooltipEnabled && point && point.options)
                        self._showTooltip(self.tooltip, point);
                    $(point).trigger('testmousehoverpoint')
                },
                mouseout: function(self, point, mode) {
                    if (self.mouseLocked)
                        return;
                    self._clearHover(self);
                    $(point).trigger('testmouseoutpoint')
                },
                touchmove: function(self, point, mode) {
                    clearTimeout(self.tooltipHoldTimeout);
                    self.tooltipHoldTimeout = null;
                    self.showHoldTooltip = true
                },
                mousemove: function(self, pageX, pageY, offsetX, offsetY) {
                    self._getCurCoords(self, pageX, pageY)
                },
                touchstart: function(self, point, mode) {
                    self.showHoldTooltip = false;
                    self._mouseLock(self);
                    if (self.tooltipEnabled)
                        self.tooltipHoldTimeout = setTimeout(function() {
                            self.showHoldTooltip = true;
                            self._showTooltip(self.tooltip, point);
                            $(point).trigger('testHoldTooltip')
                        }, TOOLTIP_HOLD_TIMEOUT)
                },
                touchend: function(self, point, mode, event) {
                    if (!self.showHoldTooltip)
                        self._pointClick(self, point, true, event);
                    clearTimeout(self.tooltipHoldTimeout);
                    self._clickLock(self);
                    self._clearHover(self)
                },
                click: function(self, point, mode, event) {
                    self._pointClick(self, point, false, event)
                },
                mousedown: function(self, point, mode) {
                    self._pointEvent.touchstart(self, point, mode)
                },
                mouseup: function(self, point, mode, event) {
                    self._pointEvent.touchend(self, point, mode, event)
                }
            },
            _pointCondition: {
                mouseover: function(self, point, mode, event, func) {
                    if (mode === ALL_ARGUMENTS_POINTS_MODE && self.hoveredPoint && self.hoveredPoint.argument === point.argument) {
                        self.hoverHoldTimeOut = clearTimeout(self.hoverHoldTimeOut);
                        self.hoveredObject = point;
                        func(self, point, mode);
                        $(point).trigger('testHoverHoldTimeOutCleared');
                        return
                    }
                    self._setHover(self, point, mode, func)
                },
                mouseout: function(self, point, mode, event, func) {
                    self._releaseHover(self, point, mode, func)
                },
                touchstart: !msPointerEnabled,
                touchend: !msPointerEnabled,
                mousedown: msPointerEnabled,
                mouseup: msPointerEnabled
            },
            _seriesEvent: {
                mouseover: function(self, series, mode) {
                    if (self.mouseLocked)
                        return;
                    self._setHoveredSeries(series, mode);
                    $(series).trigger('testmousehoverseries')
                },
                mouseout: function(self, series, mode) {
                    self._clearHover(self);
                    $(series).trigger('testmouseoutseries')
                },
                mousemove: function(self, pageX, pageY, offsetX, offsetY) {
                    self._getCurCoords(self, pageX, pageY)
                },
                touchstart: function(self) {
                    self._mouseLock(self)
                },
                touchend: function(self, series, _, event) {
                    self._seriesClick(self, series, true, event);
                    self._clickLock(self)
                },
                click: function(self, series, mode, event) {
                    self._seriesClick(self, series, false, event)
                },
                mousedown: function(self, point, mode) {
                    self._seriesEvent.touchstart(self, point, mode)
                },
                mouseup: function(self, point, mode) {
                    self._seriesEvent.touchend(self, point, mode)
                }
            },
            _crossHairEvent: {
                mousemove: function(self, x, y) {
                    if (!self.eventType) {
                        self.eventType = 'mouse';
                        return
                    }
                    else if (self.eventType === 'touch')
                        return;
                    else if (self.eventType === 'mouse') {
                        self._moveCrossHair(self, x, y);
                        self.eventType = null
                    }
                },
                mouseout: function(self) {
                    self._hideCrossHair(self);
                    self.eventType = null
                },
                touchstart: function(self, x, y) {
                    self.eventType = 'touch'
                },
                touchend: function(self, x, y) {
                    self.eventType = null
                },
                mousedown: function(self, x, y) {
                    self._crossHairEvent.touchstart(self, x, y)
                },
                mouseup: function(self, x, y) {
                    self._crossHairEvent.touchend(self, x, y)
                }
            },
            _hideCrossHair: function(self) {
                if (!self.crossHairOptions)
                    return;
                var horizontalLine = self.crossHairOptions.horizontalLine,
                    verticalLine = self.crossHairOptions.verticalLine;
                horizontalLine && horizontalLine.applySettings({visibility: 'hidden'});
                verticalLine && verticalLine.applySettings({visibility: 'hidden'})
            },
            _moveCrossHair: function(self, x, y) {
                if (!self.crossHairOptions)
                    return;
                var horizontalLine = self.crossHairOptions.horizontalLine,
                    verticalLine = self.crossHairOptions.verticalLine,
                    canvas = self.crossHairOptions.canvas || {};
                if (x > canvas.left && x < canvas.width - canvas.right && y > canvas.top && y < canvas.height - canvas.bottom) {
                    horizontalLine && horizontalLine.applySettings({visibility: 'visible'});
                    verticalLine && verticalLine.applySettings({visibility: 'visible'});
                    horizontalLine && horizontalLine.applySettings({translateY: y - canvas.top});
                    verticalLine && verticalLine.applySettings({translateX: x - canvas.left})
                }
                else {
                    horizontalLine && horizontalLine.applySettings({visibility: 'hidden'});
                    verticalLine && verticalLine.applySettings({visibility: 'hidden'})
                }
            },
            _seriesCondition: {
                mouseover: function(self, series, mode, event, func) {
                    self._setHover(self, series, mode, func)
                },
                mouseout: function(self, series, mode, event, func) {
                    self._releaseHover(self, series, mode, func)
                },
                touchstart: !msPointerEnabled,
                touchend: !msPointerEnabled,
                mousedown: msPointerEnabled,
                mouseup: msPointerEnabled
            },
            _axisEvent: {
                mouseover: function(self, axis, argument) {
                    if (self.mouseLocked || isDefined(self.hoveredArgument) && self.hoveredArgument === argument)
                        return;
                    self._clearHover(self);
                    if (isDefined(self.hoveredArgument))
                        self._toAllArgumentPoints(self.hoveredArgument, 'releasePointHoverState');
                    self._toAllArgumentPoints(argument, 'setPointHoverState');
                    self.hoveredArgument = argument;
                    $(axis).trigger('testmousehoveraxis')
                },
                mouseout: function(self, axis) {
                    if (self.mouseLocked || !isDefined(self.hoveredArgument))
                        return;
                    self._toAllArgumentPoints(self.hoveredArgument, 'releasePointHoverState');
                    self.hoveredArgument = null;
                    $(axis).trigger('testmouseoutaxis')
                },
                mousemove: function(self, pageX, pageY) {
                    self._getCurCoords(self, pageX, pageY)
                },
                touchstart: function(self) {
                    self._mouseLock(self)
                },
                touchend: function(self, axis, mode, argument, event) {
                    self._argumentAxisClick(self, axis, argument, true, event);
                    self._clearHover(self);
                    self._clickLock(self)
                },
                click: function(self, axis, mode, argument, event) {
                    self._clearHover(self);
                    self._argumentAxisClick(self, axis, argument, false, event);
                    self._clickLock(self)
                },
                mousedown: function(self) {
                    self._axisEvent.touchstart(self)
                },
                mouseup: function(self, axis, mode, argument, event) {
                    self._axisEvent.touchend(self, axis, mode, argument, event)
                }
            },
            _axisCondition: {
                mouseover: function(self, axis, mode, argument, event, func) {
                    self._hideCrossHair(self);
                    if (mode === ALL_ARGUMENTS_POINTS_MODE)
                        self._setHover(self, axis, argument, func)
                },
                mouseout: function(self, axis, mode, argument, event, func) {
                    self._releaseHover(self, axis, argument, func)
                },
                touchstart: !msPointerEnabled,
                touchend: !msPointerEnabled,
                mousedown: msPointerEnabled,
                mouseup: msPointerEnabled
            },
            _setHover: function(self, object, mode, func) {
                if (object === self.hoveredObject) {
                    self.hoverHoldTimeOut = clearTimeout(self.hoverHoldTimeOut);
                    if (mode === object.lastHoverMode)
                        return
                }
                if (self.mouseLocked)
                    return;
                self.hoverStartTimeOut = setTimeout(function() {
                    self._compareCoords(object, self, mode, func)
                }, self.hoverStartDelay)
            },
            _releaseHover: function(self, object, mode, func) {
                if (self.mouseLocked)
                    return;
                self.hoverStartTimeOut = clearTimeout(self.hoverStartTimeOut);
                if (object === self.hoveredObject)
                    self.hoverHoldTimeOut = setTimeout(function() {
                        self.hoveredObject = null;
                        func(self, object, mode)
                    }, self.hoverHoldDelay)
            },
            _compareCoords: function(point, self, mode, func) {
                clearTimeout(self.hoverStartTimeOut);
                if (Math.abs(self.pX - self.cX) + Math.abs(self.pY - self.cY) < self.sensitivity) {
                    if (self.mouseLocked)
                        return;
                    clearTimeout(self.hoverHoldTimeOut);
                    self.hoveredObject = point;
                    func(self, point, mode)
                }
                else {
                    self.pX = self.cX;
                    self.pY = self.cY;
                    self.hoverStartTimeOut = setTimeout(function() {
                        self._compareCoords(point, self, mode, func)
                    }, self.hoverStartDelay)
                }
            },
            _seriesClick: function(self, series, touchEvent, event) {
                if (self.lockClick && !touchEvent)
                    return;
                self.seriesClick && self.seriesClick.call(series, series, event)
            },
            _legendClick: function(self, series, touchEvent, event) {
                var legendClick = self.legendClick;
                if (self.lockClick && !touchEvent)
                    return true;
                if (legendClick) {
                    legendClick.call(series, series, event);
                    return true
                }
                return false
            },
            _pointClick: function(self, point, touchEvent, event) {
                var series = point.series;
                if (self.lockClick && !touchEvent)
                    return;
                if (self.pointClick) {
                    self.pointClick.call(point, point, event);
                    return
                }
                self.seriesClick && self.seriesClick.call(series, series, event);
                return
            },
            _argumentAxisClick: function(self, axis, argument, touchEvent, event) {
                if (self.lockClick && !touchEvent)
                    return;
                self.argumentAxisClick && self.argumentAxisClick.call(axis, axis, argument, event)
            },
            _selectSeries: function(event, mode) {
                event.data.tracker._setSelectedSeries(event.target, mode)
            },
            _deselectSeries: function(event, mode) {
                event.data.tracker._releaseSelectedSeries(event.target, mode)
            },
            _selectPoint: function(event, point) {
                event.data.tracker._setSelectedPoint(point)
            },
            _deselectPoint: function(event, point) {
                event.data.tracker._releaseSelectedPoint(point)
            },
            _showPointTooltip: function(event, point) {
                var self = event.data.tracker;
                self._showTooltip(self.tooltip, point)
            },
            _hidePointTooltip: function(event, point) {
                event.data.tracker._hideTooltip(point)
            },
            _hideTooltip: function(point) {
                var tooltip = this && this.tooltip;
                if (!tooltip || point && this.pointAtShownTooltip !== point)
                    return;
                point = point || this.pointAtShownTooltip;
                tooltip.hide();
                if (this.pointAtShownTooltip) {
                    this.pointAtShownTooltip = null;
                    isFunction(this.tooltipHidden) && this.tooltipHidden.call(point, point)
                }
            },
            _showTooltip: function(tooltip, point) {
                var tooltipFormatObject = point.getTooltipFormatObject(tooltip);
                if (!isDefined(tooltipFormatObject.valueText) && !tooltipFormatObject.points)
                    return;
                this.pointAtShownTooltip && this._hideTooltip(this.pointAtShownTooltip);
                if (point && point.options) {
                    var tooltipCoords = point.getTooltipCoords();
                    var tooltipText = tooltip.formatTooltip.call(tooltipFormatObject, tooltip.options);
                    if (!isDefined(tooltipText) || !isDefined(tooltipCoords.x) || !isDefined(tooltipCoords.y) || !tooltip)
                        return;
                    tooltip.show();
                    tooltip.move(~~tooltipCoords.x, ~~tooltipCoords.y, tooltipCoords.offset, tooltipText, point.getColor(), point.getClassName());
                    !this.pointAtShownTooltip && isFunction(this.tooltipShown) && this.tooltipShown.call(point, point);
                    this.pointAtShownTooltip = point
                }
            },
            _setHoveredSeries: function(series, mode) {
                var self = this;
                if (mode !== NONE_MODE && self.hoveredSeries !== series || series.lastHoverMode !== mode) {
                    self._clearHover(self);
                    self.hoveredSeries = series;
                    series.setHoverState(mode);
                    self.seriesHover && self.seriesHover.call(series, series);
                    self.seriesHoverChanged && self.seriesHoverChanged.call(series, series)
                }
                if (mode === NONE_MODE)
                    $(series).trigger('NoneMode')
            },
            _setSelectedSeries: function(series, mode) {
                var self = this,
                    seriesContain = false;
                if (this.seriesSelectionMode === MULTIPLE_MODE)
                    $.each(self.selectedSeries, function(_, sr) {
                        if (sr == series) {
                            seriesContain = true;
                            return false
                        }
                    });
                else if (self.selectedSeries == series)
                    seriesContain = true;
                if (!seriesContain || series.lastSelectionMode !== mode) {
                    if (self.seriesSelectionMode === SINGLE_MODE) {
                        this._releaseSelectedSeries();
                        self.selectedSeries = series
                    }
                    else
                        self.selectedSeries.push(series);
                    series.setSelectedState(mode);
                    self.seriesSelected && self.seriesSelected.call(series, series);
                    self.seriesSelectionChanged && self.seriesSelectionChanged.call(series, series)
                }
            },
            _setHoveredPoint: function(point, mode) {
                var self = this;
                var debug = DX.utils.debug;
                debug.assert(point.series, 'series was not assigned to point or empty');
                if (self.hoveredPoint === point && !point.series)
                    return;
                self._clearHover(self);
                self.hoveredPoint = point;
                if (point && point.options)
                    self._setHoverStylePointWithMode(point, 'setPointHoverState', mode || point.options.hoverMode, self.pointHoverChanged);
                self.pointHover && self.pointHover.call(point, point)
            },
            _toAllArgumentPoints: function(argument, func, callBack) {
                var _this = this;
                $.each(_this.storedSeries, function(_, series) {
                    var neighborPoint = series.getPointByArg(argument);
                    if (neighborPoint) {
                        series[func](neighborPoint);
                        callBack && callBack.call(neighborPoint, neighborPoint)
                    }
                })
            },
            _setHoverStylePointWithMode: function(point, func, mode, callBack) {
                var _this = this;
                switch (mode) {
                    case ALL_ARGUMENTS_POINTS_MODE:
                        this._toAllArgumentPoints(point.argument, func, callBack);
                        break;
                    case ALL_SERIES_POINTS_MODE:
                        $.each(point.series.points, function(_, point) {
                            point.series[func](point);
                            callBack && callBack.call(point, point)
                        });
                        break;
                    case NONE_MODE:
                        break;
                    default:
                        point.series[func](point);
                        callBack && callBack.call(point, point)
                }
            },
            _setSelectedPoint: function(point) {
                var self = this,
                    pointContain = false;
                if (this.pointSelectionMode === MULTIPLE_MODE) {
                    $.each(self.selectedPoint, function(_, pt) {
                        if (pt == point) {
                            pointContain = true;
                            return false
                        }
                    });
                    !pointContain && self.selectedPoint.push(point)
                }
                else if (self.selectedPoint !== point) {
                    this._releaseSelectedPoint();
                    self.selectedPoint = point
                }
                else
                    pointContain = true;
                if (!pointContain) {
                    self._setHoverStylePointWithMode(point, 'setPointSelectedState', point.options.selectionMode, self.pointSelectionChanged);
                    self.pointSelected && self.pointSelected.call(point, point)
                }
            },
            _releaseHoveredSeries: function() {
                if (!this.hoveredSeries)
                    return;
                this.hoveredSeries.releaseHoverState();
                this.seriesHoverChanged && this.seriesHoverChanged.call(this.hoveredSeries, this.hoveredSeries);
                this.hoveredSeries = null
            },
            _releaseSelectedSeriesMultiMode: function(series) {
                if (!this.selectedSeries)
                    return;
                series.releaseSelectedState();
                this.seriesSelectionChanged && this.seriesSelectionChanged.call(series, series);
                this.selectedSeries = $.map(this.selectedSeries, function(sr) {
                    if (sr !== series)
                        return sr
                })
            },
            _releaseSelectedSeriesSingleMode: function() {
                var series = this.selectedSeries;
                if (!series)
                    return;
                series.releaseSelectedState();
                this.seriesSelectionChanged && this.seriesSelectionChanged.call(series, series);
                this.selectedSeries = null
            },
            _releaseHoveredPoint: function() {
                var self = this,
                    point = self.hoveredPoint;
                if (!point || !point.options)
                    return;
                if (point.options.hoverMode === ALL_SERIES_POINTS_MODE)
                    $.each(point.series.points, function(_, point) {
                        point.series.releasePointHoverState(point);
                        self.pointHoverChanged && self.pointHoverChanged.call(point, point)
                    });
                else if (point.options.hoverMode === ALL_ARGUMENTS_POINTS_MODE)
                    self._toAllArgumentPoints(point.argument, 'releasePointHoverState', self.pointHoverChanged);
                else {
                    point.releaseHoverState();
                    self.pointHoverChanged && self.pointHoverChanged.call(point, point)
                }
                if (self.tooltipEnabled && !self.showHoldTooltip)
                    self._hideTooltip(point);
                self.hoveredPoint = null
            },
            _releaseSelectedPointMultiMode: function(point) {
                var self = this,
                    points = self.selectedPoint;
                if (!points)
                    return;
                self._setHoverStylePointWithMode(point, 'releasePointSelectedState', point.options.selectionMode, self.pointSelectionChanged);
                this.selectedPoint = $.map(this.selectedPoint, function(pt) {
                    if (pt !== point)
                        return pt
                })
            },
            _releaseSelectedPointSingleMode: function() {
                var self = this,
                    point = self.selectedPoint;
                if (!point)
                    return;
                self._setHoverStylePointWithMode(point, 'releasePointSelectedState', point.options.selectionMode, self.pointSelectionChanged);
                this.selectedPoint = null
            },
            clearSelection: function() {
                var self = this;
                if (this.pointSelectionMode === SINGLE_MODE)
                    this._releaseSelectedPoint();
                else
                    $.each(this.selectedPoint, function(_, point) {
                        self._releaseSelectedPoint(point)
                    });
                if (this.seriesSelectionMode === SINGLE_MODE)
                    this._releaseSelectedSeries();
                else
                    $.each(this.selectedSeries, function(_, series) {
                        self._releaseSelectedSeries(series)
                    })
            },
            _mouseLock: function(tracker) {
                if (tracker.unlockMouseTimer)
                    clearTimeout(tracker.unlockMouseTimer);
                tracker.mouseLocked = true;
                tracker.unlockMouseTimer = setTimeout(function() {
                    tracker.mouseLocked = false
                }, MOUSE_EVENT_LOCK_TIMEOUT)
            },
            _clickLock: function(tracker) {
                tracker.lockClick = true;
                if (tracker.lockClickTimer)
                    clearTimeout(tracker.lockClickTimer);
                tracker.lockClickTimer = setTimeout(function() {
                    tracker.lockClick = false
                }, CLICK_EVENT_LOCK_TIMEOUT)
            },
            _getCurCoords: function(self, pageX, pageY) {
                self.cX = pageX;
                self.cY = pageY
            },
            _clearHover: function(self) {
                self._releaseHoveredSeries();
                self._releaseHoveredPoint()
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-charts, file dxChart.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        ui.registerComponent("dxChart", viz.charts.Chart)
    })(jQuery, DevExpress);
    /*! Module viz-charts, file dxPieChart.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        ui.registerComponent("dxPieChart", viz.charts.PieChart)
    })(jQuery, DevExpress);
    DevExpress.MOD_VIZ_CHARTS = true
}
if (!DevExpress.MOD_VIZ_GAUGES) {
    if (!window.DevExpress)
        throw Error('Required module is not referenced: core');
    if (!DevExpress.MOD_VIZ_CORE)
        throw Error('Required module is not referenced: viz-core');
    /*! Module viz-gauges, file namespaces.js */
    (function(DX) {
        DX.viz.gauges = {__internals: {
                circularNeedles: {},
                circularMarkers: {},
                linearNeedles: {},
                linearMarkers: {}
            }};
        DX.viz.gauges.__tests = {}
    })(DevExpress);
    /*! Module viz-gauges, file factory.js */
    (function(DX, undefined) {
        var internals = DX.viz.gauges.__internals,
            circularNeedles = internals.circularNeedles,
            circularMarkers = internals.circularMarkers,
            linearNeedles = internals.linearNeedles,
            linearMarkers = internals.linearMarkers;
        var _String = window.String,
            isString = DX.utils.isString;
        DX.viz.gauges.__factory = {
            createTranslator: function(fromAngle, toAngle, fromValue, toValue) {
                return new DX.viz.core.Translator1D(fromValue, toValue, fromAngle, toAngle)
            },
            createRenderer: function(options) {
                return new DX.viz.renderers.Renderer(options)
            },
            createCircularValueIndicator: function(type) {
                var indicatorType = circularNeedles.RectangleNeedle;
                switch (_String(type).toLowerCase()) {
                    case'rectangleneedle':
                    case'rectangle':
                        indicatorType = circularNeedles.RectangleNeedle;
                        break;
                    case'triangleneedle':
                    case'triangle':
                        indicatorType = circularNeedles.TriangleNeedle;
                        break;
                    case'twocolorneedle':
                    case'twocolorrectangle':
                        indicatorType = circularNeedles.TwoColorRectangleNeedle;
                        break;
                    case'rangebar':
                        indicatorType = internals.CircularRangeBar;
                        break
                }
                return new indicatorType
            },
            createLinearValueIndicator: function(type) {
                var indicatorType = internals.LinearRangeBar;
                switch (_String(type).toLowerCase()) {
                    case'rectangle':
                        indicatorType = linearNeedles.RectangleNeedle;
                        break;
                    case'rhombus':
                        indicatorType = linearNeedles.RhombusNeedle;
                        break;
                    case'circle':
                        indicatorType = linearNeedles.CircleNeedle;
                        break;
                    case'rangebar':
                        indicatorType = internals.LinearRangeBar;
                        break
                }
                return new indicatorType
            },
            createCircularSubvalueIndicator: function(type) {
                var indicatorType = circularMarkers.TriangleMarker;
                switch (_String(type).toLowerCase()) {
                    case'trianglemarker':
                    case'triangle':
                        indicatorType = circularMarkers.TriangleMarker;
                        break;
                    case'textcloud':
                        indicatorType = circularMarkers.TextCloudMarker;
                        break
                }
                return new indicatorType
            },
            createLinearSubvalueIndicator: function(type) {
                var indicatorType = linearMarkers.TriangleMarker;
                switch (_String(type).toLowerCase()) {
                    case'trianglemarker':
                    case'triangle':
                        indicatorType = linearMarkers.TriangleMarker;
                        break;
                    case'textcloud':
                        indicatorType = linearMarkers.TextCloudMarker;
                        break
                }
                return new indicatorType
            },
            createCircularNeedle: function(type) {
                if (isString(type))
                    switch (type.toLowerCase()) {
                        case'rectangleneedle':
                        case'rectangle':
                            return new circularNeedles.RectangleNeedle;
                        case'twocolorneedle':
                        case'twocolorrectangle':
                            return new circularNeedles.TwoColorRectangleNeedle;
                        case'triangleneedle':
                        case'triangle':
                            return new circularNeedles.TriangleNeedle;
                        case'rangebar':
                            return new internals.CircularRangeBar
                    }
                return undefined
            },
            createLinearNeedle: function(type) {
                if (isString(type))
                    switch (type.toLowerCase()) {
                        case'rectangle':
                            return new linearNeedles.RectangleNeedle;
                        case'rhombus':
                            return new linearNeedles.RhombusNeedle;
                        case'circle':
                            return new linearNeedles.CircleNeedle;
                        case'rangebar':
                            return new internals.LinearRangeBar
                    }
                return undefined
            },
            createCircularMarker: function(type) {
                if (isString(type))
                    switch (type.toLowerCase()) {
                        case'trianglemarker':
                        case'triangle':
                            return new circularMarkers.TriangleMarker;
                        case'textcloud':
                            return new circularMarkers.TextCloudMarker
                    }
                return undefined
            },
            createLinearMarker: function(type) {
                if (isString(type))
                    switch (type.toLowerCase()) {
                        case'trianglemarker':
                        case'triangle':
                            return new linearMarkers.TriangleMarker;
                        case'textcloud':
                            return new linearMarkers.TextCloudMarker
                    }
                return undefined
            },
            createCircularRangeBar: function() {
                return new internals.CircularRangeBar
            },
            createLinearRangeBar: function() {
                return new internals.LinearRangeBar
            },
            createCircularScale: function() {
                return new internals.CircularScale
            },
            createLinearScale: function() {
                return new internals.LinearScale
            },
            createCircularRangeContainer: function() {
                return new internals.CircularRangeContainer
            },
            createLinearRangeContainer: function() {
                return new internals.LinearRangeContainer
            },
            createTitle: function() {
                return new internals.Title
            },
            createIndicator: function() {
                return internals.Indicator && new internals.Indicator || null
            },
            createTooltip: function(parameters) {
                return new internals.Tooltip(parameters)
            },
            createLayoutManager: function() {
                return new internals.LayoutManager
            },
            createThemeManager: function(options) {
                return new internals.ThemeManager(options)
            },
            createTracker: function(parameters) {
                return new internals.Tracker(parameters)
            }
        };
        var isFunction = DX.utils.isFunction,
            String = window.String;
        var formatHelper = DX.formatHelper;
        internals.formatValue = function(value, options) {
            options = options || {};
            var text = formatHelper.format(value, options.format, options.precision),
                context;
            isFunction(options.customizeText) && (context = {
                value: value,
                valueText: text
            });
            return context ? String(options.customizeText.call(context, context)) : text
        };
        internals.getSampleText = function(translator, options) {
            var text1 = internals.formatValue(translator.getDomainStart(), options),
                text2 = internals.formatValue(translator.getDomainEnd(), options);
            return text1.length >= text2.length ? text1 : text2
        }
    })(DevExpress);
    /*! Module viz-gauges, file scale.js */
    (function(DX, $, undefined) {
        var formatHelper = DX.formatHelper;
        var getCosAndSin = DX.utils.getCosAndSin,
            normalizeAngle = DX.utils.normalizeAngle,
            convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace,
            isDefined = DX.utils.isDefined,
            isString = DX.utils.isString,
            isFunction = DX.utils.isFunction,
            isArray = DX.utils.isArray,
            isNaN = window.isNaN,
            Number = window.Number,
            String = window.String,
            max = Math.max,
            min = Math.min,
            abs = Math.abs,
            atan = Math.atan,
            acos = Math.acos,
            ceil = Math.ceil,
            $extend = $.extend,
            $map = $.map;
        var PI = Math.PI;
        var tickProvider = DX.viz.core.tickProvider;
        function binarySearch(x, list) {
            var a = 0,
                b = list.length - 1,
                flag = list[a] - list[b] < 0,
                c,
                k = -1;
            if (list[a] === x)
                k = a;
            if (list[b] === x)
                k = b;
            while (k < 0 && a <= b) {
                c = ~~((a + b) / 2);
                if (list[c] === x)
                    k = c;
                else if (list[c] - x < 0 === flag)
                    a = c + 1;
                else
                    b = c - 1
            }
            return k
        }
        DX.viz.gauges.__internals.BaseScale = DX.Class.inherit({
            setup: function(parameters) {
                var self = this;
                DX.utils.debug.assertParam(parameters.renderer, '"renderer" is not passed');
                DX.utils.debug.assertParam(parameters.translator, '"translator" is not passed');
                DX.utils.debug.assertParam(parameters.owner, '"owner" is not passed');
                DX.utils.debug.assertParam(parameters.incidentOccured, '"incidentOccured" is not passed');
                self._renderer = parameters.renderer;
                self._translator = parameters.translator;
                self._owner = parameters.owner;
                self._incidentOccured = parameters.incidentOccured;
                self._rootElement = self._renderer.createGroup({'class': 'dxg-scale'});
                self._majorTicks = self._renderer.createGroup({'class': 'dxg-major-ticks'}).append(self._rootElement);
                self._minorTicks = self._renderer.createGroup({'class': 'dxg-minor-ticks'}).append(self._rootElement);
                self._labels = self._renderer.createGroup({'class': 'dxg-labels'}).append(self._rootElement);
                return self
            },
            dispose: function() {
                var self = this;
                self.clear();
                delete self._renderer;
                delete self._translator;
                delete self._owner;
                delete self._incidentOccured;
                delete self._rootElement;
                delete self._majorTicks;
                delete self._minorTicks;
                delete self._labels;
                return self
            },
            init: function(options) {
                var self = this;
                self._options = $extend(true, self._options || {}, options);
                self._options.majorTick || (self._options.majorTick = {});
                self._options.minorTick || (self._options.minorTick = {});
                if (options && options.majorTick && isDefined(options.majorTick.customTickValues))
                    self._options.majorTick.customTickValues = isArray(options.majorTick.customTickValues) ? options.majorTick.customTickValues.slice(0) : null;
                if (options && options.minorTick && isDefined(options.minorTick.customTickValues))
                    self._options.minorTick.customTickValues = isArray(options.minorTick.customTickValues) ? options.minorTick.customTickValues.slice(0) : null;
                delete self._processed;
                return self
            },
            _getCustomValues: function(values, compare) {
                var translator = this._translator,
                    result = [];
                if (isArray(values)) {
                    result = $map(values, function(x) {
                        return !isNaN(translator.translate(x)) ? Number(x) : null
                    }).sort(compare);
                    result = $map(result, function(x, i) {
                        return x !== result[i - 1] ? x : null
                    })
                }
                return result
            },
            _getTicks: function() {
                var self = this,
                    options = self._options,
                    translator = self._translator,
                    startValue = translator.getDomainStart(),
                    endValue = translator.getDomainEnd(),
                    compare = startValue < endValue ? function(x, y) {
                        return x - y
                    } : function(x, y) {
                        return y - x
                    },
                    gridSpacingFactor = self._getGridSpacingFactor(),
                    info,
                    majorValues,
                    minorValues,
                    customMajorValues,
                    customMinorValues,
                    list,
                    ticks = {};
                info = tickProvider.getFullTicks(startValue, endValue, self._getScreenDelta(), {
                    tickInterval: options.majorTick.tickInterval > 0 ? Number(options.majorTick.tickInterval) : undefined,
                    gridSpacingFactor: gridSpacingFactor.majorTicks,
                    numberMultipliers: [1, 2, 5]
                }, {
                    tickInterval: options.minorTick.tickInterval > 0 ? Number(options.minorTick.tickInterval) : undefined,
                    gridSpacingFactor: gridSpacingFactor.minorTicks,
                    numberMultipliers: [1, 2, 5]
                });
                if (options.majorTick.showCalculatedTicks) {
                    majorValues = info.majorTicks;
                    if (options.majorTick.useTicksAutoArrangement)
                        majorValues = self._cutTicks(majorValues)
                }
                else
                    majorValues = [];
                customMajorValues = self._getCustomValues(options.majorTick.customTickValues, compare);
                customMajorValues = $map(customMajorValues, function(value) {
                    return binarySearch(value, majorValues) === -1 ? value : null
                });
                if (options.minorTick.showCalculatedTicks)
                    minorValues = info.minorTicks;
                else
                    minorValues = [];
                minorValues = $map(minorValues, function(value) {
                    return binarySearch(value, customMajorValues) === -1 ? value : null
                });
                customMinorValues = self._getCustomValues(options.minorTick.customTickValues, compare);
                list = majorValues.concat(minorValues, customMajorValues).sort(compare);
                customMinorValues = $map(customMinorValues, function(value) {
                    return binarySearch(value, list) === -1 ? value : null
                });
                ticks.major = $map(majorValues.concat(customMajorValues), function(value) {
                    return {
                            value: value,
                            position: translator.translate(value)
                        }
                });
                ticks.minor = $map(minorValues.concat(customMinorValues), function(value) {
                    return {
                            value: value,
                            position: translator.translate(value)
                        }
                });
                return ticks
            },
            _cutTicks: function(values) {
                var self = this,
                    factor = self._getCuttingFactor(values.length, {
                        width: self._textWidth,
                        height: self._textHeight
                    }),
                    cutValues = [],
                    i = 0,
                    ii = values.length;
                for (; i < ii; i += factor)
                    cutValues.push(values[i]);
                return cutValues
            },
            _renderContent: function(ticks) {
                var self = this,
                    options = self._options,
                    i,
                    ii,
                    item,
                    points,
                    element,
                    textPosition,
                    textValue;
                if (self._majorTickLength && self._majorTickWidth) {
                    self._majorTicks.applySettings({fill: isString(options.majorTick.color) ? options.majorTick.color : 'none'});
                    points = self._getTickPoints(self._majorTickLength, self._majorTickWidth);
                    i = 0;
                    ii = ticks.major.length;
                    options.hideFirstTick === true && ++i;
                    options.hideLastTick === true && --ii;
                    for (; i < ii; ++i) {
                        item = ticks.major[i];
                        element = self._renderer.createArea(points);
                        self._moveTick(element, item);
                        element.append(self._majorTicks)
                    }
                }
                if (self._minorTickLength && self._minorTickWidth) {
                    self._minorTicks.applySettings({fill: isString(options.minorTick.color) ? options.minorTick.color : 'none'});
                    points = self._getTickPoints(self._minorTickLength, self._minorTickWidth);
                    for (i = 0, ii = ticks.minor.length; i < ii; ++i) {
                        item = ticks.minor[i];
                        element = self._renderer.createArea(points);
                        self._moveTick(element, item);
                        element.append(self._minorTicks)
                    }
                }
                if (self._textIndent) {
                    self._labels.applySettings({
                        align: self._getLabelAlign(self._textIndent),
                        font: options.label.font
                    });
                    textPosition = self._getLabelPosition(self._majorTickLength || 0, self._textIndent);
                    i = 0;
                    ii = ticks.major.length;
                    options.hideFirstLabel === true && ++i;
                    options.hideLastLabel === true && --ii;
                    for (; i < ii; ++i) {
                        item = ticks.major[i];
                        textValue = self._formatValue(item.value);
                        points = self._getLabelOptions(textValue, textPosition, self._textIndent, item);
                        self._renderer.createText(textValue, points.x, points.y + self._textVerticalOffset).append(self._labels)
                    }
                }
            },
            _processOptions: function() {
                var self = this,
                    options = self._options;
                if (self._processed)
                    return;
                self._processed = true;
                self._setupOrientation();
                self._majorTickLength = self._majorTickWidth = self._minorTickLength = self._minorTickWidth = self._textIndent = 0;
                if (options.majorTick.visible) {
                    if (options.majorTick.length > 0)
                        self._majorTickLength = Number(options.majorTick.length);
                    else
                        self._incidentOccured('Major ticks are not rendered because the value of "majorTick.length" option is not valid');
                    if (options.majorTick.width > 0)
                        self._majorTickWidth = Number(options.majorTick.width);
                    else
                        self._incidentOccured('Major ticks are not rendered because the value of "majorTick.width" option is not valid')
                }
                if (options.minorTick.visible) {
                    if (options.minorTick.length > 0)
                        self._minorTickLength = Number(options.minorTick.length);
                    else
                        self._incidentOccured('Minor ticks are not rendered because the value of "minorTick.length" option is not valid');
                    if (options.minorTick.width > 0)
                        self._minorTickWidth = Number(options.minorTick.width);
                    else
                        self._incidentOccured('Minor ticks are not rendered because the value of "minorTick.width" option is not valid')
                }
                if (options.label.visible)
                    if (Number(options.label.indentFromTick) !== 0) {
                        self._textIndent = Number(options.label.indentFromTick);
                        self._measureText()
                    }
                    else
                        self._incidentOccured('Labels are not rendered because the value of the "label.indentFromTick" option is not valid')
            },
            render: function() {
                var self = this,
                    ticks;
                self._majorTicks.clear();
                self._minorTicks.clear();
                self._labels.clear();
                self._processOptions();
                if (self._isVisible()) {
                    self._rendered = true;
                    self._rootElement.append(self._owner);
                    ticks = self._getTicks();
                    self._renderContent(ticks)
                }
                else
                    self.clear();
                return self
            },
            clear: function() {
                var self = this;
                if (self._rendered) {
                    self._rendered = false;
                    self._rootElement.detach();
                    self._majorTicks.clear();
                    self._minorTicks.clear();
                    self._labels.clear()
                }
                return self
            },
            _formatValue: function(value) {
                var labelOptions = this._options.label,
                    result = formatHelper.format(value, labelOptions.format, labelOptions.precision);
                if (isFunction(labelOptions.customizeText)) {
                    result = {
                        value: value,
                        valueText: result
                    };
                    result = String(labelOptions.customizeText.call(result, result))
                }
                return result
            },
            _getSampleText: function() {
                var self = this,
                    start = self._translator.getDomainStart(),
                    end = self._translator.getDomainEnd(),
                    texts = [],
                    i,
                    ii,
                    text,
                    maxLength = 0,
                    maxText;
                var ticks = tickProvider.getTicks({
                        min: start,
                        max: end,
                        tickInterval: self._options.majorTick.tickInterval,
                        screenDelta: self._options.approximateScreenDelta,
                        gridSpacingFactor: self._getGridSpacingFactor().majorTicks
                    });
                for (i = 0, ii = ticks.length; i < ii; ++i) {
                    text = self._formatValue(ticks[i]);
                    text.length > maxLength && (maxText = text) && (maxLength = text.length)
                }
                return maxText
            },
            _measureText: function() {
                var self = this,
                    value = self._getSampleText(),
                    text = self._renderer.createText(value, 0, 0, {font: self._options.label.font}).append(self._labels),
                    bbox;
                self._rendered || self._rootElement.append(self._owner);
                bbox = text.getBBox();
                self._rendered || self._rootElement.detach();
                text.remove();
                self._textVerticalOffset = -bbox.y - bbox.height / 2;
                self._textWidth = bbox.width;
                self._textHeight = bbox.height;
                self._textLength = value.length
            }
        });
        function getBasedAngle(startAngle, endAngle) {
            var startDelta,
                endDelta,
                tmp;
            if (startAngle > endAngle) {
                tmp = endAngle;
                endAngle = startAngle;
                startAngle = tmp
            }
            startDelta = 0 <= startAngle && startAngle <= 180 ? abs(90 - startAngle) : abs(270 - startAngle);
            startDelta = startAngle < 90 && 90 < endAngle || startAngle < 270 && 270 < endAngle ? 0 : startDelta;
            endDelta = 0 < endAngle && endAngle < 180 ? abs(90 - endAngle) : abs(270 - endAngle);
            return startDelta < endDelta ? startDelta : endDelta
        }
        DX.viz.gauges.__internals.CircularScale = DX.viz.gauges.__internals.BaseScale.inherit({
            _getGridSpacingFactor: function() {
                return {
                        majorTicks: 17,
                        minorTicks: 5
                    }
            },
            _getScreenDelta: function() {
                var self = this;
                return (self._translator.getCodomainStart() - self._translator.getCodomainEnd()) * self._options.radius * PI / 180
            },
            _getCuttingFactor: function(ticksCount, maxLabelSize) {
                var self = this,
                    options = self._options,
                    startAngle = self._translator.getCodomainStart(),
                    endAngle = self._translator.getCodomainEnd(),
                    radius = self._getLabelPosition(self._majorTickLength || 0, self._textIndent),
                    baseAngle = getBasedAngle(normalizeAngle(startAngle), normalizeAngle(endAngle)),
                    baseAngleCosSin = getCosAndSin(baseAngle),
                    degreesPerTick = (startAngle - endAngle) / ticksCount,
                    minAngleBetweenTicks,
                    widthBasedAngle,
                    tanOfWidthBasedAngle,
                    heightBasedAngle,
                    cosOfHeightBasedAngle,
                    cuttingBackFactor = 1;
                tanOfWidthBasedAngle = (baseAngleCosSin.sin * radius + maxLabelSize.width) / (baseAngleCosSin.cos * radius);
                widthBasedAngle = abs(baseAngle - atan(tanOfWidthBasedAngle) * 180 / PI);
                cosOfHeightBasedAngle = baseAngleCosSin.cos - maxLabelSize.height / radius;
                heightBasedAngle = -1 > cosOfHeightBasedAngle || cosOfHeightBasedAngle > 1 ? 90 : abs(baseAngle - acos(cosOfHeightBasedAngle) * 180 / PI);
                minAngleBetweenTicks = widthBasedAngle < heightBasedAngle ? widthBasedAngle : heightBasedAngle;
                if (degreesPerTick < minAngleBetweenTicks)
                    cuttingBackFactor = ceil(minAngleBetweenTicks / degreesPerTick);
                return max(1, cuttingBackFactor)
            },
            _setupOrientation: function() {
                var self = this,
                    inner = 0,
                    outer = 0;
                switch (self._options.orientation) {
                    case'inside':
                        inner = 1;
                        break;
                    case'center':
                        inner = outer = 0.5;
                        break;
                    default:
                        self._options.orientation !== 'outside' && self._incidentOccured('The value of the "orientation" option is not valid');
                        outer = 1;
                        break
                }
                self._inner = inner;
                self._outer = outer
            },
            _getTickPoints: function(length, width) {
                var options = this._options,
                    x1 = options.x - width / 2,
                    x2 = options.x + width / 2,
                    y1 = options.y - options.radius - length * this._outer,
                    y2 = options.y - options.radius + length * this._inner;
                return [x1, y1, x2, y1, x2, y2, x1, y2]
            },
            _moveTick: function(element, tick) {
                element.rotate(convertAngleToRendererSpace(tick.position), this._options.x, this._options.y)
            },
            _getLabelPosition: function(tickLength, textIndent) {
                return this._options.radius + tickLength * (textIndent >= 0 ? this._outer : -this._inner) + textIndent
            },
            _getLabelAlign: function() {
                return 'center'
            },
            _getLabelOptions: function(textValue, textPosition, textIndent, tick) {
                var self = this,
                    options = self._options,
                    cossin = getCosAndSin(tick.position),
                    x = options.x + cossin.cos * textPosition,
                    y = options.y - cossin.sin * textPosition,
                    dx = cossin.cos * (textValue.length / self._textLength) * self._textWidth / 2,
                    dy = cossin.sin * self._textHeight / 2;
                if (textIndent > 0) {
                    x += dx;
                    y -= dy
                }
                else {
                    x -= dx;
                    y += dy
                }
                return {
                        x: x,
                        y: y
                    }
            },
            _isVisible: function() {
                var self = this,
                    length = self._majorTickLength || 0,
                    r = self._options.radius,
                    inner = r - self._inner * length,
                    outer = r + self._outer * length;
                return inner > 0 && outer > inner
            },
            measure: function() {
                var self = this,
                    options = self._options,
                    result = {
                        min: options.radius,
                        max: options.radius
                    };
                self._processOptions();
                if (self._majorTickLength) {
                    result.min -= self._inner * self._majorTickLength;
                    result.max += self._outer * self._majorTickLength
                }
                if (self._textIndent) {
                    if (self._textIndent >= 0) {
                        result.horizontalOffset = self._textIndent + self._textWidth;
                        result.verticalOffset = self._textIndent + self._textHeight
                    }
                    else {
                        result.horizontalOffset = 0;
                        result.verticalOffset = 0;
                        result.min += self._textIndent - max(self._textWidth, self._textHeight)
                    }
                    result.inverseHorizontalOffset = self._textWidth / 2;
                    result.inverseVerticalOffset = self._textHeight / 2
                }
                return result
            }
        });
        DX.viz.gauges.__internals.LinearScale = DX.viz.gauges.__internals.BaseScale.inherit({
            _getGridSpacingFactor: function() {
                return {
                        majorTicks: 25,
                        minorTicks: 5
                    }
            },
            _getScreenDelta: function() {
                return abs(this._translator.getCodomainEnd() - this._translator.getCodomainStart())
            },
            _getCuttingFactor: function(ticksCount, maxLabelSize) {
                var self = this,
                    labelSize = self._vertical ? maxLabelSize.height : maxLabelSize.width,
                    screenSize = abs(self._translator.getCodomainEnd() - self._translator.getCodomainStart());
                return max(1, ceil(ticksCount * labelSize / (screenSize + labelSize)))
            },
            _setupOrientation: function() {
                var self = this,
                    inner = 0,
                    outer = 0;
                self._vertical = self._options.orientation === 'vertical';
                if (self._vertical)
                    switch (self._options.horizontalOrientation) {
                        case'left':
                            inner = 1;
                            break;
                        case'center':
                            inner = outer = 0.5;
                            break;
                        default:
                            self._options.horizontalOrientation !== 'right' && self._incidentOccured('The value of the "horizontalOrientation" option is not valid');
                            outer = 1;
                            break
                    }
                else
                    switch (self._options.verticalOrientation) {
                        case'top':
                            inner = 1;
                            break;
                        case'middle':
                            inner = outer = 0.5;
                            break;
                        default:
                            self._options.verticalOrientation !== 'bottom' && self._incidentOccured('The value of the "verticalOrientation" option is not valid');
                            outer = 1;
                            break
                    }
                self._inner = inner;
                self._outer = outer
            },
            _getTickPoints: function(length, width) {
                var options = this._options,
                    x1,
                    x2,
                    y1,
                    y2;
                if (this._vertical) {
                    x1 = options.x - length * this._inner;
                    x2 = options.x + length * this._outer;
                    y1 = -width / 2;
                    y2 = width / 2
                }
                else {
                    x1 = -width / 2;
                    x2 = width / 2;
                    y1 = options.y - length * this._inner;
                    y2 = options.y + length * this._outer
                }
                return [x1, y1, x2, y1, x2, y2, x1, y2]
            },
            _moveTick: function(element, tick) {
                var options = this._options,
                    x = 0,
                    y = 0;
                if (this._vertical)
                    y = tick.position;
                else
                    x = tick.position;
                element.move(x, y)
            },
            _getLabelPosition: function(tickLength, textIndent) {
                var options = this._options,
                    position = tickLength * (textIndent >= 0 ? this._outer : -this._inner) + textIndent;
                if (this._vertical)
                    position += options.x;
                else
                    position += options.y + (textIndent >= 0 ? 1 : -1) * this._textVerticalOffset;
                return position
            },
            _getLabelAlign: function(textIndent) {
                return this._vertical ? textIndent > 0 ? 'left' : 'right' : 'center'
            },
            _getLabelOptions: function(textValue, textPosition, textIndent, tick) {
                var x,
                    y;
                if (this._vertical) {
                    x = textPosition;
                    y = tick.position
                }
                else {
                    x = tick.position;
                    y = textPosition
                }
                return {
                        x: x,
                        y: y
                    }
            },
            _isVisible: function() {
                return true
            },
            measure: function() {
                var self = this,
                    options = self._options,
                    result;
                self._processOptions();
                if (self._vertical) {
                    result = {
                        min: options.x,
                        max: options.x
                    };
                    if (self._majorTickLength) {
                        result.min -= self._inner * self._majorTickLength;
                        result.max += self._outer * self._majorTickLength
                    }
                    if (self._textIndent) {
                        if (self._textIndent >= 0)
                            result.max += self._textIndent + self._textWidth;
                        else
                            result.min += self._textIndent - self._textWidth;
                        result.indent = self._textHeight / 2
                    }
                }
                else {
                    result = {
                        min: options.y,
                        max: options.y
                    };
                    if (self._majorTickLength) {
                        result.min -= self._inner * self._majorTickLength;
                        result.max += self._outer * self._majorTickLength
                    }
                    if (self._textIndent) {
                        if (self._textIndent >= 0)
                            result.max += self._textIndent + self._textHeight;
                        else
                            result.min += self._textIndent - self._textHeight;
                        result.indent = self._textWidth / 2
                    }
                }
                return result
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file baseIndicator.js */
    (function(DX, $, undefined) {
        var isFinite = window.isFinite,
            Number = window.Number,
            $extend = $.extend;
        DX.viz.gauges.__internals.BaseIndicator = DX.Class.inherit({
            setup: function(parameters) {
                var self = this;
                self._renderer = parameters.renderer;
                self._translator = parameters.translator;
                self._owner = parameters.owner;
                self._tracker = parameters.tracker;
                self._className = parameters.className;
                self._options = {};
                return self
            },
            init: function(options) {
                this._options = $extend(true, this._options || {}, options);
                return this
            },
            _setupAnimation: function() {
                var self = this;
                if (self._options.animationEnabled) {
                    self._animation || (self._animation = {step: function(pos) {
                            self._actualValue = self._animation.start + self._animation.delta * pos;
                            self._actualPosition = self._translator.translate(self._actualValue);
                            self._move()
                        }});
                    self._animation.duration = self._options.animationDuration > 0 ? Number(self._options.animationDuration) : 0
                }
                else
                    delete self._animation
            },
            _runAnimation: function(value) {
                var self = this,
                    animation = self._animation;
                animation.start = self._actualValue;
                animation.delta = value - self._actualValue;
                self._rootElement.animate({_: 0}, {
                    step: animation.step,
                    duration: animation.duration
                })
            },
            _createRoot: function() {
                return this._renderer.createGroup({'class': this._className})
            },
            _createTracker: function() {
                return this._renderer.createArea()
            },
            _getTrackerSettings: function(){},
            render: function() {
                var self = this;
                self._actualValue = self._currentValue = self._translator.adjust(self._options.currentValue);
                self._actualPosition = self._translator.translate(self._actualValue);
                if (self._isVisible()) {
                    self._setupAnimation();
                    self._rootElement = self._rootElement || self._createRoot();
                    self._rootElement.applySettings({fill: self._options.color});
                    self._rootElement.append(self._owner);
                    self._render();
                    self._trackerElement = self._trackerElement || self._createTracker();
                    self._trackerElement.applySettings(self._getTrackerSettings());
                    self._tracker.attach(self._trackerElement, self, self._trackerInfo);
                    self._move()
                }
                else
                    self.clear();
                return self
            },
            clear: function() {
                var self = this;
                if (self._rootElement) {
                    self._animation && self._rootElement.stopAnimation() && (self._animation = null);
                    self._rootElement.detach();
                    self._rootElement.dispose();
                    self._rootElement = null;
                    self._clear();
                    self._tracker.detach(self._trackerElement);
                    self._trackerElement = null
                }
                return self
            },
            value: function(arg) {
                var self = this,
                    val;
                if (arguments.length) {
                    val = self._translator.adjust(arg);
                    if (self._currentValue !== val && isFinite(val)) {
                        self._currentValue = val;
                        if (self._rootElement)
                            if (self._animation)
                                self._runAnimation(val);
                            else {
                                self._actualValue = val;
                                self._actualPosition = self._translator.translate(val);
                                self._move()
                            }
                    }
                    return self
                }
                return self._currentValue
            },
            _isVisible: function() {
                throw new Error('_isVisible - not implemented');
            },
            _render: function() {
                throw new Error('_render - not implemented');
            },
            _clear: function() {
                throw new Error('_clear - not implemented');
            },
            _move: function() {
                throw new Error('_move - not implemented');
            },
            getCurrentValue: function() {
                return this.value()
            },
            setCurrentValue: function(value) {
                return this.value(value)
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file baseMarker.js */
    (function(DX, undefined) {
        var TextCloud = DX.viz.core.TextCloud;
        var formatValue = DX.viz.gauges.__internals.formatValue,
            getSampleText = DX.viz.gauges.__internals.getSampleText;
        DX.viz.gauges.__internals.BaseTextCloudMarker = DX.viz.gauges.__internals.BaseIndicator.inherit({
            _move: function() {
                var self = this,
                    bbox,
                    info = new TextCloud,
                    textCloudOptions = self._getTextCloudOptions();
                self._text.applySettings({text: formatValue(self._actualValue, self._options.text)});
                bbox = self._text.getBBox();
                info.setup({
                    x: textCloudOptions.x,
                    y: textCloudOptions.y,
                    textWidth: bbox.width,
                    textHeight: bbox.height,
                    horMargin: self._options.horizontalOffset,
                    verMargin: self._options.verticalOffset,
                    tailLength: self._options.arrowLength,
                    type: textCloudOptions.type
                });
                self._text.applySettings({
                    x: info.cx(),
                    y: info.cy() + self._textVerticalOffset
                });
                self._cloud.applySettings({points: info.points()});
                self._trackerElement && self._trackerElement.applySettings({points: info.points()})
            },
            _measureText: function() {
                var self = this,
                    root,
                    text,
                    bbox;
                if (!self._textVerticalOffset) {
                    root = self._createRoot().append(self._owner);
                    text = self._renderer.createText(getSampleText(self._translator, self._options.text), 0, 0, {
                        align: 'center',
                        font: self._options.text.font
                    }).append(root);
                    bbox = text.getBBox();
                    root.remove();
                    self._textVerticalOffset = -bbox.y - bbox.height / 2;
                    self._textWidth = bbox.width;
                    self._textHeight = bbox.height;
                    self._textFullWidth = self._textWidth + 2 * self._options.horizontalOffset;
                    self._textFullHeight = self._textHeight + 2 * self._options.verticalOffset
                }
            },
            _render: function() {
                var self = this;
                self._measureText();
                self._cloud = self._cloud || self._renderer.createArea().append(self._rootElement);
                self._text = self._text || self._renderer.createText().append(self._rootElement);
                self._text.applySettings({
                    align: 'center',
                    font: self._options.text.font
                })
            },
            _clear: function() {
                delete this._cloud;
                delete this._text
            },
            getTooltipParameters: function() {
                var position = this._getTextCloudOptions();
                return {
                        x: position.x,
                        y: position.y,
                        value: this._currentValue,
                        color: this._options.color
                    }
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file baseRangeBar.js */
    (function(DX, $, undefined) {
        var $extend = $.extend;
        var formatValue = DX.viz.gauges.__internals.formatValue,
            getSampleText = DX.viz.gauges.__internals.getSampleText;
        DX.viz.gauges.__internals.BaseRangeBar = DX.viz.gauges.__internals.BaseIndicator.inherit({
            _measureText: function() {
                var self = this,
                    root,
                    text,
                    bbox;
                self._hasText = self._isTextVisible();
                if (self._hasText && !self._textVerticalOffset) {
                    root = self._createRoot().append(self._owner);
                    text = self._renderer.createText(getSampleText(self._translator, self._options.text), 0, 0, {
                        'class': 'dxg-text',
                        align: 'center',
                        font: self._options.text.font
                    }).append(root);
                    bbox = text.getBBox();
                    root.remove();
                    self._textVerticalOffset = -bbox.y - bbox.height / 2;
                    self._textWidth = bbox.width;
                    self._textHeight = bbox.height
                }
            },
            _move: function() {
                var self = this;
                self._updateBarItemsPositions();
                if (self._hasText) {
                    self._text.applySettings({text: formatValue(self._actualValue, self._options.text)});
                    self._updateTextPosition();
                    self._updateLinePosition()
                }
            },
            _updateBarItems: function() {
                var self = this,
                    options = self._options,
                    backgroundColor,
                    spaceColor;
                self._setBarSides();
                self._startPosition = self._translator.translate(self._translator.getDomainStart());
                self._endPosition = self._translator.translate(self._translator.getDomainEnd());
                self._basePosition = self._translator.translate(options.baseValue);
                self._space = self._getSpace();
                backgroundColor = options.backgroundColor || 'none';
                if (backgroundColor !== 'none' && self._space > 0)
                    spaceColor = options.containerBackgroundColor || 'none';
                else {
                    self._space = 0;
                    spaceColor = 'none'
                }
                self._backItem1.applySettings({fill: backgroundColor});
                self._backItem2.applySettings({fill: backgroundColor});
                self._spaceItem1.applySettings({fill: spaceColor});
                self._spaceItem2.applySettings({fill: spaceColor})
            },
            _getSpace: function() {
                return 0
            },
            _updateTextItems: function() {
                var self = this;
                if (self._hasText) {
                    self._line = self._line || self._renderer.createPath([], {'class': 'dxg-main-bar'}).append(self._rootElement);
                    self._text = self._text || self._renderer.createText('', 0, 0, {'class': 'dxg-text'}).append(self._rootElement);
                    self._text.applySettings({
                        align: self._getTextAlign(),
                        font: self._getFontOptions()
                    });
                    self._setTextItemsSides()
                }
                else {
                    if (self._line) {
                        self._line.remove();
                        delete self._line
                    }
                    if (self._text) {
                        self._text.remove();
                        delete self._text
                    }
                }
            },
            _isTextVisible: function() {
                return false
            },
            _getTextAlign: function() {
                return 'center'
            },
            _getFontOptions: function() {
                var options = this._options,
                    font = options.text.font;
                if (!font || !font.color)
                    font = $extend({}, font, {color: options.color});
                return font
            },
            _updateBarItemsPositions: function() {
                var self = this,
                    positions = self._getPositions();
                self._backItem1.applySettings(self._buildItemSettings(positions.start, positions.back1));
                self._backItem2.applySettings(self._buildItemSettings(positions.back2, positions.end));
                self._spaceItem1.applySettings(self._buildItemSettings(positions.back1, positions.main1));
                self._spaceItem2.applySettings(self._buildItemSettings(positions.main2, positions.back2));
                self._mainItem.applySettings(self._buildItemSettings(positions.main1, positions.main2));
                self._trackerElement && self._trackerElement.applySettings(self._buildItemSettings(positions.main1, positions.main2))
            },
            _render: function() {
                var self = this;
                self._measureText();
                if (!self._backItem1) {
                    self._backItem1 = self._createBarItem();
                    self._backItem1.applySettings({'class': 'dxg-back-bar'})
                }
                if (!self._backItem2) {
                    self._backItem2 = self._createBarItem();
                    self._backItem2.applySettings({'class': 'dxg-back-bar'})
                }
                if (!self._spaceItem1) {
                    self._spaceItem1 = self._createBarItem();
                    self._spaceItem1.applySettings({'class': 'dxg-space-bar'})
                }
                if (!self._spaceItem2) {
                    self._spaceItem2 = self._createBarItem();
                    self._spaceItem2.applySettings({'class': 'dxg-space-bar'})
                }
                if (!self._mainItem) {
                    self._mainItem = self._createBarItem();
                    self._mainItem.applySettings({'class': 'dxg-main-bar'})
                }
                self._updateBarItems();
                self._updateTextItems()
            },
            _clear: function() {
                var self = this;
                delete self._backItem1;
                delete self._backItem2;
                delete self._spaceItem1;
                delete self._spaceItem2;
                delete self._mainItem;
                delete self._hasText;
                delete self._line;
                delete self._text
            },
            getTooltipParameters: function() {
                var position = this._getTooltipPosition();
                return {
                        x: position.x,
                        y: position.y,
                        value: this._currentValue,
                        color: this._options.color,
                        offset: 0
                    }
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file circularNeedle.js */
    (function(DX, undefined) {
        var circularNeedles = DX.viz.gauges.__internals.circularNeedles;
        circularNeedles.SimpleIndicator = DX.viz.gauges.__internals.BaseIndicator.inherit({
            _move: function() {
                var self = this,
                    options = self._options,
                    angle = DX.utils.convertAngleToRendererSpace(self._actualPosition);
                self._rootElement.rotate(angle, options.x, options.y);
                self._trackerElement && self._trackerElement.rotate(angle, options.x, options.y)
            },
            _isVisible: function() {
                var options = this._options;
                return options.width > 0 && options.indentFromCenter >= 0 && options.radius - options.indentFromCenter > 0
            },
            _getTrackerSettings: function() {
                var options = this._options,
                    x = options.x,
                    y = options.y - (options.radius + options.indentFromCenter) / 2,
                    width = options.width / 2,
                    length = (options.radius - options.indentFromCenter) / 2;
                width > 10 || (width = 10);
                length > 10 || (length = 10);
                return {points: [x - width, y - length, x - width, y + length, x + width, y + length, x + width, y - length]}
            },
            _renderSpindle: function() {
                var self = this,
                    options = self._options,
                    gapSize;
                if (options.spindleSize > 0) {
                    gapSize = Number(options.spindleGapSize) || 0;
                    if (gapSize > 0)
                        gapSize = gapSize <= options.spindleSize ? gapSize : options.spindleSize;
                    self._spindleOuter = self._spindleOuter || self._renderer.createCircle().append(self._rootElement);
                    self._spindleInner = self._spindleInner || self._renderer.createCircle().append(self._rootElement);
                    self._spindleOuter.applySettings({
                        'class': 'dxg-spindle-border',
                        cx: options.x,
                        cy: options.y,
                        r: options.spindleSize / 2
                    });
                    self._spindleInner.applySettings({
                        'class': 'dxg-spindle-hole',
                        cx: options.x,
                        cy: options.y,
                        r: gapSize / 2,
                        fill: options.containerBackgroundColor
                    })
                }
                else
                    self._clearSpindle()
            },
            _render: function() {
                var self = this,
                    options = self._options;
                self._renderPointer();
                self._renderSpindle()
            },
            _clearSpindle: function() {
                delete this._spindleOuter;
                delete this._spindleInner
            },
            _clearPointer: function() {
                delete this._element
            },
            _clear: function() {
                this._clearPointer();
                this._clearSpindle()
            },
            measure: function() {
                var options = this._options,
                    result = {max: options.radius};
                if (options.indentFromCenter < 0)
                    result.inverseHorizontalOffset = result.inverseVerticalOffset = -options.indentFromCenter;
                return result
            },
            getTooltipParameters: function() {
                var options = this._options,
                    cossin = DX.utils.getCosAndSin(this._actualPosition),
                    r = (options.radius + options.indentFromCenter) / 2;
                return {
                        x: options.x + cossin.cos * r,
                        y: options.y - cossin.sin * r,
                        value: this._currentValue,
                        color: options.color,
                        offset: options.width / 2
                    }
            }
        });
        circularNeedles.RectangleNeedle = circularNeedles.SimpleIndicator.inherit({_renderPointer: function() {
                var self = this,
                    options = self._options,
                    y2 = options.y - options.radius,
                    y1 = options.y - options.indentFromCenter || options.y,
                    x1 = options.x - options.width / 2 || options.x,
                    x2 = x1 + options.width || options.x;
                self._element = self._element || self._renderer.createArea().append(self._rootElement);
                self._element.applySettings({points: [x1, y1, x1, y2, x2, y2, x2, y1]})
            }});
        circularNeedles.TriangleNeedle = circularNeedles.SimpleIndicator.inherit({_renderPointer: function() {
                var self = this,
                    options = self._options,
                    y2 = options.y - options.radius,
                    y1 = options.y - options.indentFromCenter || options.y,
                    x1 = options.x - options.width / 2 || options.x,
                    x2 = options.x + options.width / 2 || options.x;
                self._element = self._element || self._renderer.createArea().append(self._rootElement);
                self._element.applySettings({points: [x1, y1, options.x, y2, x2, y1]})
            }});
        circularNeedles.TwoColorRectangleNeedle = circularNeedles.SimpleIndicator.inherit({
            _renderPointer: function() {
                var self = this,
                    options = self._options,
                    x1 = options.x - options.width / 2 || options.x,
                    x2 = options.x + options.width / 2 || options.x,
                    y4 = options.y - options.radius,
                    y1 = options.y - options.indentFromCenter || options.y,
                    y3 = y4 + (y1 - y4) * options.secondFraction || y4,
                    y2 = y3 + options.space || y3;
                self._firstElement = self._firstElement || self._renderer.createArea().append(self._rootElement);
                self._spaceElement = self._spaceElement || self._renderer.createArea().append(self._rootElement);
                self._secondElement = self._secondElement || self._renderer.createArea().append(self._rootElement);
                self._firstElement.applySettings({points: [x1, y1, x1, y2, x2, y2, x2, y1]});
                self._spaceElement.applySettings({
                    points: [x1, y2, x1, y3, x2, y3, x2, y2],
                    'class': 'dxg-hole',
                    fill: options.containerBackgroundColor
                });
                self._secondElement.applySettings({
                    points: [x1, y3, x1, y4, x2, y4, x2, y3],
                    'class': 'dxg-part',
                    fill: options.secondColor
                })
            },
            _clearPointer: function() {
                delete this._firstElement;
                delete this._secondElement;
                delete this._spaceElement
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file linearNeedle.js */
    (function(DX, undefined) {
        var linearNeedles = DX.viz.gauges.__internals.linearNeedles;
        linearNeedles.SimpleIndicator = DX.viz.gauges.__internals.BaseIndicator.inherit({
            _move: function() {
                var self = this,
                    delta = self._actualPosition - self._zeroPosition;
                self._rootElement.move(self._vertical ? 0 : delta, self._vertical ? delta : 0);
                self._trackerElement && self._trackerElement.move(self._vertical ? 0 : delta, self._vertical ? delta : 0)
            },
            _isVisible: function() {
                var options = this._options;
                return options.length > 0 && options.width > 0
            },
            _getTrackerSettings: function() {
                var options = this._options,
                    x1,
                    x2,
                    y1,
                    y2,
                    width = options.width / 2,
                    length = options.length / 2,
                    p = this._zeroPosition;
                width > 10 || (width = 10);
                length > 10 || (length = 10);
                if (this._vertical) {
                    x1 = options.x - length;
                    x2 = options.x + length;
                    y1 = p + width || p;
                    y2 = p - width || p
                }
                else {
                    x1 = p - width;
                    x2 = p + width;
                    y1 = options.y + length;
                    y2 = options.y - length
                }
                return {points: [x1, y1, x1, y2, x2, y2, x2, y1]}
            },
            _render: function() {
                var self = this;
                self._zeroPosition = self._translator.getCodomainStart()
            },
            _clear: function() {
                delete this._element
            },
            init: function(options) {
                var self = this;
                self.callBase(options);
                self._vertical = self._options.orientation === 'vertical';
                return self
            },
            measure: function() {
                var options = this._options,
                    p = this._vertical ? options.x : options.y;
                return {
                        min: p - options.length / 2,
                        max: p + options.length / 2
                    }
            },
            getTooltipParameters: function() {
                var self = this,
                    options = self._options,
                    p = self._actualPosition,
                    parameters = {
                        x: p,
                        y: p,
                        value: self._currentValue,
                        color: options.color,
                        offset: options.width / 2
                    };
                self._vertical ? parameters.x = options.x : parameters.y = options.y;
                return parameters
            }
        });
        linearNeedles.RectangleNeedle = linearNeedles.SimpleIndicator.inherit({_render: function() {
                var self = this,
                    options = self._options,
                    p,
                    x1,
                    x2,
                    y1,
                    y2;
                self.callBase();
                p = self._zeroPosition;
                if (self._vertical) {
                    x1 = options.x - options.length / 2 || options.x;
                    x2 = options.x + options.length / 2 || options.x;
                    y1 = p + options.width / 2 || p;
                    y2 = p - options.width / 2 || p
                }
                else {
                    x1 = p - options.width / 2 || p;
                    x2 = p + options.width / 2 || p;
                    y1 = options.y + options.length / 2 || options.y;
                    y2 = options.y - options.length / 2 || options.y
                }
                self._element = self._element || self._renderer.createArea().append(self._rootElement);
                self._element.applySettings({points: [x1, y1, x1, y2, x2, y2, x2, y1]})
            }});
        linearNeedles.RhombusNeedle = linearNeedles.SimpleIndicator.inherit({_render: function() {
                var self = this,
                    options = self._options,
                    x,
                    y,
                    dx,
                    dy;
                self.callBase();
                if (self._vertical) {
                    x = options.x;
                    y = self._zeroPosition;
                    dx = options.length / 2 || 0;
                    dy = options.width / 2 || 0
                }
                else {
                    x = self._zeroPosition;
                    y = options.y;
                    dx = options.width / 2 || 0;
                    dy = options.length / 2 || 0
                }
                self._element = self._element || self._renderer.createArea().append(self._rootElement);
                self._element.applySettings({points: [x - dx, y, x, y - dy, x + dx, y, x, y + dy]})
            }});
        linearNeedles.CircleNeedle = linearNeedles.SimpleIndicator.inherit({_render: function() {
                var self = this,
                    options = self._options,
                    x,
                    y,
                    r;
                self.callBase();
                if (self._vertical) {
                    x = options.x;
                    y = self._zeroPosition
                }
                else {
                    x = self._zeroPosition;
                    y = options.y
                }
                r = options.length / 2 || 0;
                self._element = self._element || self._renderer.createCircle().append(self._rootElement);
                self._element.applySettings({
                    cx: x,
                    cy: y,
                    r: r
                })
            }})
    })(DevExpress);
    /*! Module viz-gauges, file circularMarker.js */
    (function(DX, undefined) {
        var circularMarkers = DX.viz.gauges.__internals.circularMarkers;
        circularMarkers.TriangleMarker = DX.viz.gauges.__internals.circularNeedles.SimpleIndicator.inherit({
            _isVisible: function() {
                var options = this._options;
                return options.length > 0 && options.width > 0 && options.radius > 0
            },
            _render: function() {
                var self = this,
                    options = self._options,
                    x = options.x,
                    y1 = options.y - options.radius,
                    dx = options.width / 2 || 0,
                    y2 = y1 - options.length,
                    settings;
                self._element = self._element || self._renderer.createArea().append(self._rootElement);
                settings = {
                    points: [x, y1, x - dx, y2, x + dx, y2],
                    stroke: 'none',
                    strokeWidth: 0
                };
                if (options.space > 0) {
                    settings.strokeWidth = Math.min(options.space, options.width / 4) || 0;
                    settings.stroke = settings.strokeWidth > 0 ? options.containerBackgroundColor || 'none' : 'none'
                }
                self._element.applySettings(settings)
            },
            _clear: function() {
                delete this._element
            },
            _getTrackerSettings: function() {
                var options = this._options,
                    x = options.x,
                    y = options.y - options.radius - options.length / 2,
                    width = options.width / 2,
                    length = options.length / 2;
                width > 10 || (width = 10);
                length > 10 || (length = 10);
                return {points: [x - width, y - length, x - width, y + length, x + width, y + length, x + width, y - length]}
            },
            measure: function() {
                var options = this._options;
                return {
                        min: options.radius,
                        max: options.radius + options.length || options.radius
                    }
            },
            getTooltipParameters: function() {
                var options = this._options,
                    cossin = DX.utils.getCosAndSin(this._actualPosition),
                    r = options.radius + options.length / 2,
                    parameters = this.callBase();
                parameters.x = options.x + cossin.cos * r;
                parameters.y = options.y - cossin.sin * r;
                parameters.offset = options.length / 2;
                return parameters
            }
        });
        circularMarkers.TextCloudMarker = DX.viz.gauges.__internals.BaseTextCloudMarker.inherit({
            _isVisible: function() {
                return this._options.radius > 0
            },
            _getTextCloudOptions: function() {
                var self = this,
                    cossin = DX.utils.getCosAndSin(self._actualPosition),
                    nangle = DX.utils.normalizeAngle(self._actualPosition);
                return {
                        x: self._options.x + cossin.cos * self._options.radius,
                        y: self._options.y - cossin.sin * self._options.radius,
                        type: nangle > 270 ? 'left-top' : nangle > 180 ? 'top-right' : nangle > 90 ? 'right-bottom' : 'bottom-left'
                    }
            },
            measure: function() {
                var self = this;
                self._measureText();
                return {
                        min: self._options.radius,
                        max: self._options.radius,
                        horizontalOffset: self._textFullWidth + self._options.arrowLength,
                        verticalOffset: self._textFullHeight + self._options.arrowLength
                    }
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file linearMarker.js */
    (function(DX, undefined) {
        var linearMarkers = DX.viz.gauges.__internals.linearMarkers;
        linearMarkers.TriangleMarker = DX.viz.gauges.__internals.linearNeedles.SimpleIndicator.inherit({
            _render: function() {
                var self = this,
                    options = self._options,
                    x1,
                    x2,
                    y1,
                    y2,
                    settings = {
                        stroke: 'none',
                        strokeWidth: 0
                    };
                self.callBase();
                if (self._vertical) {
                    x1 = options.x;
                    y1 = self._zeroPosition;
                    x2 = x1 + (self._inverted ? options.length : -options.length);
                    settings.points = [x1, y1, x2, y1 - options.width / 2, x2, y1 + options.width / 2]
                }
                else {
                    y1 = options.y;
                    x1 = self._zeroPosition;
                    y2 = y1 + (self._inverted ? options.length : -options.length);
                    settings.points = [x1, y1, x1 - options.width / 2, y2, x1 + options.width / 2, y2]
                }
                if (options.space > 0) {
                    settings.strokeWidth = Math.min(options.space, options.width / 4) || 0;
                    settings.stroke = settings.strokeWidth > 0 ? options.containerBackgroundColor || 'none' : 'none'
                }
                self._element = self._element || self._renderer.createArea().append(self._rootElement);
                self._element.applySettings(settings)
            },
            _getTrackerSettings: function() {
                var self = this,
                    options = self._options,
                    width = options.width / 2,
                    length = options.length,
                    x1,
                    x2,
                    y1,
                    y2,
                    result;
                width > 10 || (width = 10);
                length > 20 || (length = 20);
                if (self._vertical) {
                    x1 = x2 = options.x;
                    x2 = x1 + (self._inverted ? length : -length);
                    y1 = self._zeroPosition + width;
                    y2 = self._zeroPosition - width;
                    result = [x1, y1, x2, y1, x2, y2, x1, y2]
                }
                else {
                    y1 = options.y;
                    y2 = y1 + (self._inverted ? length : -length);
                    x1 = self._zeroPosition - width;
                    x2 = self._zeroPosition + width;
                    result = [x1, y1, x1, y2, x2, y2, x2, y1]
                }
                return {points: result}
            },
            init: function(options) {
                var self = this;
                self.callBase(options);
                self._inverted = self._vertical ? self._options.horizontalOrientation === 'right' : self._options.verticalOrientation === 'bottom';
                return self
            },
            measure: function() {
                var self = this,
                    options = self._options,
                    minbound,
                    maxbound,
                    indent = options.width / 2 || 0;
                if (self._vertical) {
                    minbound = maxbound = options.x;
                    if (self._inverted)
                        maxbound = minbound + options.length || minbound;
                    else
                        minbound = maxbound - options.length || maxbound
                }
                else {
                    minbound = maxbound = options.y;
                    if (self._inverted)
                        maxbound = minbound + options.length || minbound;
                    else
                        minbound = maxbound - options.length || maxbound
                }
                return {
                        min: minbound,
                        max: maxbound,
                        indent: indent
                    }
            },
            getTooltipParameters: function() {
                var self = this,
                    options = self._options,
                    s = (self._inverted ? options.length : -options.length) / 2,
                    parameters = self.callBase();
                self._vertical ? parameters.x += s : parameters.y += s;
                parameters.offset = options.length / 2;
                return parameters
            }
        });
        linearMarkers.TextCloudMarker = DX.viz.gauges.__internals.BaseTextCloudMarker.inherit({
            _isVisible: function() {
                return true
            },
            _getTextCloudOptions: function() {
                var self = this,
                    x = self._actualPosition,
                    y = self._actualPosition,
                    type;
                if (self._vertical) {
                    x = self._options.x;
                    type = self._inverted ? 'top-left' : 'top-right'
                }
                else {
                    y = self._options.y;
                    type = self._inverted ? 'right-top' : 'right-bottom'
                }
                return {
                        x: x,
                        y: y,
                        type: type
                    }
            },
            init: function(options) {
                var self = this;
                self.callBase(options);
                self._vertical = self._options.orientation === 'vertical';
                self._inverted = self._vertical ? self._options.horizontalOrientation === 'right' : self._options.verticalOrientation === 'bottom';
                return self
            },
            measure: function() {
                var self = this,
                    options = self._options,
                    minbound,
                    maxbound,
                    indent;
                self._measureText();
                if (self._vertical) {
                    indent = self._textFullHeight;
                    if (self._inverted) {
                        minbound = options.x;
                        maxbound = options.x + options.arrowLength + self._textFullWidth
                    }
                    else {
                        minbound = options.x - options.arrowLength - self._textFullWidth;
                        maxbound = options.x
                    }
                }
                else {
                    indent = self._textFullWidth;
                    if (self._inverted) {
                        minbound = options.y;
                        maxbound = options.y + options.arrowLength + self._textFullHeight
                    }
                    else {
                        minbound = options.y - options.arrowLength - self._textFullHeight;
                        maxbound = options.y
                    }
                }
                return {
                        min: minbound,
                        max: maxbound,
                        indent: indent
                    }
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file circularRangeBar.js */
    (function(DX, undefined) {
        var getCosAndSin = DX.utils.getCosAndSin,
            convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace,
            max = Math.max,
            min = Math.min;
        DX.viz.gauges.__internals.CircularRangeBar = DX.viz.gauges.__internals.BaseRangeBar.inherit({
            _isVisible: function() {
                var options = this._options;
                return options.size > 0 && options.radius - options.size > 0
            },
            _createBarItem: function() {
                return this._renderer.createArc().append(this._rootElement)
            },
            _createTracker: function() {
                return this._renderer.createArc()
            },
            _setBarSides: function() {
                var self = this,
                    options = self._options;
                self._minSide = options.radius - options.size;
                self._maxSide = options.radius
            },
            _getSpace: function() {
                var options = this._options;
                return options.space > 0 ? options.space * 180 / options.radius / Math.PI : 0
            },
            _isTextVisible: function() {
                var options = this._options.text || {};
                return options.indent > 0
            },
            _setTextItemsSides: function() {
                var self = this,
                    options = self._options;
                self._lineFrom = options.y - options.radius;
                self._lineTo = self._lineFrom - options.text.indent;
                self._textRadius = options.radius + options.text.indent
            },
            _getPositions: function() {
                var self = this,
                    basePosition = self._basePosition,
                    actualPosition = self._actualPosition,
                    mainPosition1,
                    mainPosition2,
                    space = self._space;
                if (basePosition >= actualPosition) {
                    mainPosition1 = basePosition;
                    mainPosition2 = actualPosition
                }
                else {
                    mainPosition1 = actualPosition;
                    mainPosition2 = basePosition
                }
                return {
                        start: self._startPosition,
                        end: self._endPosition,
                        main1: mainPosition1,
                        main2: mainPosition2,
                        back1: min(mainPosition1 + space, self._startPosition),
                        back2: max(mainPosition2 - space, self._endPosition)
                    }
            },
            _buildItemSettings: function(from, to) {
                var self = this;
                return {
                        x: self._options.x,
                        y: self._options.y,
                        innerRadius: self._minSide,
                        outerRadius: self._maxSide,
                        startAngle: to,
                        endAngle: from
                    }
            },
            _updateTextPosition: function() {
                var self = this,
                    cossin = getCosAndSin(self._actualPosition),
                    x = self._options.x + self._textRadius * cossin.cos,
                    y = self._options.y - self._textRadius * cossin.sin;
                x += cossin.cos * self._textWidth / 2;
                y -= cossin.sin * self._textHeight / 2;
                self._text.applySettings({
                    x: x,
                    y: y + self._textVerticalOffset
                })
            },
            _updateLinePosition: function() {
                var self = this,
                    x = self._options.x,
                    x1,
                    x2;
                if (self._basePosition > self._actualPosition) {
                    x1 = x - 2;
                    x2 = x
                }
                else if (self._basePosition < self._actualPosition) {
                    x1 = x;
                    x2 = x + 2
                }
                else {
                    x1 = x - 1;
                    x2 = x + 1
                }
                self._line.applySettings({points: [x1, self._lineFrom, x1, self._lineTo, x2, self._lineTo, x2, self._lineFrom]});
                self._line.rotate(convertAngleToRendererSpace(self._actualPosition), x, self._options.y)
            },
            _getTooltipPosition: function() {
                var self = this,
                    cossin = getCosAndSin((self._basePosition + self._actualPosition) / 2),
                    r = (self._minSide + self._maxSide) / 2;
                return {
                        x: self._options.x + cossin.cos * r,
                        y: self._options.y - cossin.sin * r
                    }
            },
            measure: function() {
                var self = this,
                    options = self._options,
                    result = {
                        min: options.radius - options.size || options.radius,
                        max: options.radius
                    };
                self._measureText();
                if (self._hasText) {
                    result.max += options.text.indent;
                    result.horizontalOffset = self._textWidth;
                    result.verticalOffset = self._textHeight
                }
                return result
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file linearRangeBar.js */
    (function(DX, undefined) {
        DX.viz.gauges.__internals.LinearRangeBar = DX.viz.gauges.__internals.BaseRangeBar.inherit({
            _isVisible: function() {
                var options = this._options;
                return options.size > 0
            },
            init: function(options) {
                var self = this;
                self.callBase(options);
                self._vertical = self._options.orientation === 'vertical';
                self._inverted = self._vertical ? self._options.horizontalOrientation === 'right' : self._options.verticalOrientation === 'bottom';
                return self
            },
            _createBarItem: function() {
                return this._renderer.createArea().append(this._rootElement)
            },
            _createTracker: function() {
                return this._renderer.createArea()
            },
            _setBarSides: function() {
                var self = this,
                    options = self._options,
                    minSide,
                    maxSide;
                if (self._vertical)
                    if (self._inverted) {
                        minSide = options.x;
                        maxSide = options.x + options.size
                    }
                    else {
                        minSide = options.x - options.size;
                        maxSide = options.x
                    }
                else if (self._inverted) {
                    minSide = options.y;
                    maxSide = options.y + options.size
                }
                else {
                    minSide = options.y - options.size;
                    maxSide = options.y
                }
                self._minSide = minSide;
                self._maxSide = maxSide;
                self._minBound = minSide;
                self._maxBound = maxSide
            },
            _getSpace: function() {
                var options = this._options;
                return options.space > 0 ? Number(options.space) : 0
            },
            _isTextVisible: function() {
                var textOptions = this._options.text || {};
                return textOptions.indent > 0 || textOptions.indent < 0
            },
            _getTextAlign: function() {
                return this._vertical ? this._options.text.indent > 0 ? 'left' : 'right' : 'center'
            },
            _setTextItemsSides: function() {
                var self = this,
                    indent = Number(self._options.text.indent);
                if (indent > 0) {
                    self._lineStart = self._maxSide;
                    self._lineEnd = self._maxSide + indent;
                    self._textPosition = self._lineEnd + (self._vertical ? 2 : self._textHeight / 2);
                    self._maxBound = self._textPosition + (self._vertical ? self._textWidth : self._textHeight / 2)
                }
                else if (indent < 0) {
                    self._lineStart = self._minSide;
                    self._lineEnd = self._minSide + indent;
                    self._textPosition = self._lineEnd - (self._vertical ? 2 : self._textHeight / 2);
                    self._minBound = self._textPosition - (self._vertical ? self._textWidth : self._textHeight / 2)
                }
            },
            _getPositions: function() {
                var self = this,
                    options = self._options,
                    startPosition = self._startPosition,
                    endPosition = self._endPosition,
                    space = self._space,
                    basePosition = self._basePosition,
                    actualPosition = self._actualPosition,
                    mainPosition1,
                    mainPosition2,
                    backPosition1,
                    backPosition2;
                if (startPosition < endPosition) {
                    if (basePosition < actualPosition) {
                        mainPosition1 = basePosition;
                        mainPosition2 = actualPosition
                    }
                    else {
                        mainPosition1 = actualPosition;
                        mainPosition2 = basePosition
                    }
                    backPosition1 = mainPosition1 - space;
                    backPosition2 = mainPosition2 + space
                }
                else {
                    if (basePosition > actualPosition) {
                        mainPosition1 = basePosition;
                        mainPosition2 = actualPosition
                    }
                    else {
                        mainPosition1 = actualPosition;
                        mainPosition2 = basePosition
                    }
                    backPosition1 = mainPosition1 + space;
                    backPosition2 = mainPosition2 - space
                }
                return {
                        start: startPosition,
                        end: endPosition,
                        main1: mainPosition1,
                        main2: mainPosition2,
                        back1: backPosition1,
                        back2: backPosition2
                    }
            },
            _buildItemSettings: function(from, to) {
                var self = this,
                    side1 = self._minSide,
                    side2 = self._maxSide;
                var points = self._vertical ? [side1, from, side1, to, side2, to, side2, from] : [from, side1, from, side2, to, side2, to, side1];
                return {points: points}
            },
            _updateTextPosition: function() {
                var self = this;
                self._text.applySettings(self._vertical ? {
                    x: self._textPosition,
                    y: self._actualPosition + self._textVerticalOffset
                } : {
                    x: self._actualPosition,
                    y: self._textPosition + self._textVerticalOffset
                })
            },
            _updateLinePosition: function() {
                var self = this,
                    actualPosition = self._actualPosition,
                    side1,
                    side2,
                    points;
                if (self._vertical) {
                    if (self._basePosition >= actualPosition) {
                        side1 = actualPosition;
                        side2 = actualPosition + 2
                    }
                    else {
                        side1 = actualPosition - 2;
                        side2 = actualPosition
                    }
                    points = [self._lineStart, side1, self._lineStart, side2, self._lineEnd, side2, self._lineEnd, side1]
                }
                else {
                    if (self._basePosition <= actualPosition) {
                        side1 = actualPosition - 2;
                        side2 = actualPosition
                    }
                    else {
                        side1 = actualPosition;
                        side2 = actualPosition + 2
                    }
                    points = [side1, self._lineStart, side1, self._lineEnd, side2, self._lineEnd, side2, self._lineStart]
                }
                self._line.applySettings({points: points})
            },
            _getTooltipPosition: function() {
                var self = this,
                    crossCenter = (self._minSide + self._maxSide) / 2,
                    alongCenter = (self._basePosition + self._actualPosition) / 2,
                    position = {};
                if (self._vertical)
                    position = {
                        x: crossCenter,
                        y: alongCenter
                    };
                else
                    position = {
                        x: alongCenter,
                        y: crossCenter
                    };
                return position
            },
            measure: function() {
                var self = this,
                    options = self._options,
                    minbound,
                    maxbound,
                    indent;
                self._measureText();
                if (self._vertical) {
                    minbound = maxbound = options.x;
                    if (self._inverted)
                        maxbound = maxbound + options.size || maxbound;
                    else
                        minbound = minbound - options.size || minbound;
                    if (self._hasText) {
                        indent = self._textHeight / 2;
                        if (options.text.indent > 0)
                            maxbound += options.text.indent + self._textWidth;
                        if (options.text.indent < 0)
                            minbound += options.text.indent - self._textWidth
                    }
                }
                else {
                    minbound = maxbound = options.y;
                    if (self._inverted)
                        maxbound = maxbound + options.size || maxbound;
                    else
                        minbound = minbound - options.size || minbound;
                    if (self._hasText) {
                        indent = self._textWidth / 2;
                        if (options.text.indent > 0)
                            maxbound += options.text.indent + self._textHeight;
                        if (options.text.indent < 0)
                            minbound += options.text.indent - self._textHeight
                    }
                }
                return {
                        min: minbound,
                        max: maxbound,
                        indent: indent
                    }
            }
        })
    })(DevExpress);
    /*! Module viz-gauges, file rangeContainer.js */
    (function(DX, $, undefined) {
        var isDefined = DX.utils.isDefined,
            isString = DX.utils.isString,
            isArray = DX.utils.isArray,
            Number = window.Number,
            isFinite = window.isFinite,
            max = Math.max,
            abs = Math.abs,
            $each = $.each,
            $map = $.map,
            $extend = $.extend;
        function subtractSegmentAsc(segmentStart, segmentEnd, otherStart, otherEnd) {
            var result;
            if (otherStart > segmentStart && otherEnd < segmentEnd)
                result = [{
                        start: segmentStart,
                        end: otherStart
                    }, {
                        start: otherEnd,
                        end: segmentEnd
                    }];
            else if (otherStart >= segmentEnd || otherEnd <= segmentStart)
                result = [{
                        start: segmentStart,
                        end: segmentEnd
                    }];
            else if (otherStart <= segmentStart && otherEnd >= segmentEnd)
                result = [];
            else if (otherStart > segmentStart)
                result = [{
                        start: segmentStart,
                        end: otherStart
                    }];
            else if (otherEnd < segmentEnd)
                result = [{
                        start: otherEnd,
                        end: segmentEnd
                    }];
            return result
        }
        function subtractSegmentDes(segmentStart, segmentEnd, otherStart, otherEnd) {
            var result;
            if (otherStart < segmentStart && otherEnd > segmentEnd)
                result = [{
                        start: segmentStart,
                        end: otherStart
                    }, {
                        start: otherEnd,
                        end: segmentEnd
                    }];
            else if (otherStart <= segmentEnd || otherEnd >= segmentStart)
                result = [{
                        start: segmentStart,
                        end: segmentEnd
                    }];
            else if (otherStart >= segmentStart && otherEnd <= segmentEnd)
                result = [];
            else if (otherStart < segmentStart)
                result = [{
                        start: segmentStart,
                        end: otherStart
                    }];
            else if (otherEnd > segmentEnd)
                result = [{
                        start: otherEnd,
                        end: segmentEnd
                    }];
            return result
        }
        function isNotEmptySegmentAsc(start, end, threshold) {
            return end - start >= threshold
        }
        function isNotEmptySegmentDes(start, end, threshold) {
            return start - end >= threshold
        }
        DX.viz.gauges.__internals.BaseRangeContainer = DX.Class.inherit({
            setup: function(parameters) {
                var self = this;
                DX.utils.debug.assertParam(parameters.renderer, '"renderer" is not passed');
                DX.utils.debug.assertParam(parameters.renderer, '"translator" is not passed');
                DX.utils.debug.assertParam(parameters.owner, '"owner" is not passed');
                DX.utils.debug.assertParam(parameters.incidentOccured, '"incidentOccured" is not passed');
                self._renderer = parameters.renderer;
                self._translator = parameters.translator;
                self._owner = parameters.owner;
                self._incidentOccured = parameters.incidentOccured;
                return self
            },
            init: function(options) {
                var self = this;
                self._options = $extend(true, self._options || {}, options);
                if (options && isDefined(options.ranges))
                    self._options.ranges = isArray(options.ranges) ? options.ranges.slice(0) : null;
                return self
            },
            _getRanges: function() {
                var self = this,
                    options = self._options,
                    translator = self._translator,
                    totalStart = translator.getDomainStart(),
                    totalEnd = translator.getDomainEnd(),
                    totalDelta = totalEnd - totalStart,
                    isNotEmptySegment = totalDelta >= 0 ? isNotEmptySegmentAsc : isNotEmptySegmentDes,
                    subtractSegment = totalDelta >= 0 ? subtractSegmentAsc : subtractSegmentDes,
                    list = [],
                    ranges = [],
                    backgroundRanges = [{
                            start: totalStart,
                            end: totalEnd
                        }],
                    threshold = abs(totalDelta) / 1E4,
                    palette = isArray(options.palette) ? options.palette : [],
                    paletteOffset,
                    backgroundColor = isString(options.backgroundColor) ? options.backgroundColor : 'none',
                    width = options.width || {},
                    startWidth = Number(width > 0 ? width : width.start),
                    endWidth = Number(width > 0 ? width : width.end),
                    deltaWidth = endWidth - startWidth;
                if (!options.ranges) {
                    self._incidentOccured('The range container is not rendered because the value of the "ranges" option is not valid');
                    return null
                }
                if (!(startWidth >= 0 && endWidth >= 0 && startWidth + endWidth > 0)) {
                    self._incidentOccured('The range container is not rendered because the value of the "width" option is not valid');
                    return null
                }
                list = $map(options.ranges, function(rangeOptions, i) {
                    rangeOptions = rangeOptions || {};
                    var start = translator.adjust(rangeOptions.startValue),
                        end = translator.adjust(rangeOptions.endValue);
                    return isFinite(start) && isFinite(end) && isNotEmptySegment(start, end, threshold) ? {
                            start: start,
                            end: end,
                            color: rangeOptions.color,
                            classIndex: i
                        } : null
                });
                paletteOffset = max(0, palette.length - list.length);
                $each(list, function(i, item) {
                    var color = item.color;
                    isString(color) || (color = palette[i + paletteOffset]);
                    isString(color) || (color = 'none');
                    item.color = color;
                    item.className = 'dxg-range dxg-range-' + item.classIndex;
                    delete item.classIndex
                });
                $each(list, function(_, item) {
                    var i,
                        ii,
                        sub,
                        subs,
                        range,
                        newRanges = [],
                        newBackgroundRanges = [];
                    for (i = 0, ii = ranges.length; i < ii; ++i) {
                        range = ranges[i];
                        subs = subtractSegment(range.start, range.end, item.start, item.end);
                        (sub = subs[0]) && (sub.color = range.color) && (sub.className = range.className) && newRanges.push(sub);
                        (sub = subs[1]) && (sub.color = range.color) && (sub.className = range.className) && newRanges.push(sub)
                    }
                    newRanges.push(item);
                    ranges = newRanges;
                    for (i = 0, ii = backgroundRanges.length; i < ii; ++i) {
                        range = backgroundRanges[i];
                        subs = subtractSegment(range.start, range.end, item.start, item.end);
                        (sub = subs[0]) && newBackgroundRanges.push(sub);
                        (sub = subs[1]) && newBackgroundRanges.push(sub)
                    }
                    backgroundRanges = newBackgroundRanges
                });
                $each(backgroundRanges, function(_, range) {
                    range.color = backgroundColor;
                    range.className = 'dxg-range dxg-background-range';
                    ranges.push(range)
                });
                $each(ranges, function(_, range) {
                    range.startPosition = translator.translate(range.start);
                    range.endPosition = translator.translate(range.end);
                    range.startWidth = (range.start - totalStart) / totalDelta * deltaWidth + startWidth;
                    range.endWidth = (range.end - totalStart) / totalDelta * deltaWidth + startWidth
                });
                return ranges
            },
            _getRenderSettings: function() {
                throw new Error('_getRenderSettings - not implemented');
            },
            _createRange: function(settings) {
                throw new Error('_createRange - not implemented');
            },
            render: function() {
                var self = this,
                    ranges,
                    settings;
                self._rootElement = self._rootElement || self._renderer.createGroup({'class': 'dxg-range-container'});
                self._rootElement.append(self._owner).clear();
                ranges = self._getRanges();
                settings = ranges ? self._getRenderSettings() : null;
                if (settings)
                    $each(ranges, function(_, range) {
                        var element = self._createRange(range, settings);
                        element.applySettings({
                            fill: range.color,
                            'class': range.className
                        });
                        element.append(self._rootElement)
                    });
                else {
                    self._rootElement.detach();
                    self._rootElement.clear();
                    delete self._rootElement
                }
                return self
            }
        });
        DX.viz.gauges.__internals.CircularRangeContainer = DX.viz.gauges.__internals.BaseRangeContainer.inherit({
            _getRenderSettings: function() {
                var options = this._options,
                    r = options.radius,
                    inner = 0,
                    outer = 0,
                    width = options.width > 0 ? options.width : max(options.width.start, options.width.end);
                switch (options.orientation) {
                    case'inside':
                        inner = 1;
                        break;
                    case'outside':
                        outer = 1;
                        break;
                    case'center':
                        inner = outer = 0.5;
                        break;
                    default:
                        this._incidentOccured('The range container is not rendered because the value of the "orientation" option is not valid');
                        break
                }
                return (inner || outer) && r + outer * width > 0 && r - inner * width > 0 ? {
                        x: options.x,
                        y: options.y,
                        r: r,
                        inner: inner,
                        outer: outer
                    } : null
            },
            _createRange: function(range, settings) {
                var width = (range.startWidth + range.endWidth) / 2;
                return this._renderer.createArc(settings.x, settings.y, settings.r + settings.outer * width, settings.r - settings.inner * width, range.endPosition, range.startPosition)
            },
            measure: function() {
                var options = this._options,
                    radius = options.radius,
                    size = options.width || {},
                    result = null;
                size = Number(size) || max(size.start, size.end, 0) || 0;
                switch (options.orientation) {
                    case'inside':
                        result = {
                            min: radius - size,
                            max: radius
                        };
                        break;
                    case'outside':
                        result = {
                            min: radius,
                            max: radius + size
                        };
                        break;
                    case'center':
                        result = {
                            min: radius - size / 2,
                            max: radius + size / 2
                        };
                        break
                }
                return result
            }
        });
        DX.viz.gauges.__internals.LinearRangeContainer = DX.viz.gauges.__internals.BaseRangeContainer.inherit({
            _getRenderSettings: function() {
                var self = this,
                    options = self._options,
                    vertical,
                    position,
                    inner = 0,
                    outer = 0;
                if (options.orientation === 'vertical') {
                    position = options.x;
                    vertical = true;
                    switch (options.horizontalOrientation) {
                        case'left':
                            inner = 1;
                            break;
                        case'right':
                            outer = 1;
                            break;
                        case'center':
                            inner = outer = 0.5;
                            break;
                        default:
                            self._incidentOccured('The range container is not rendered because the value of the "horizontalOrientation" option is not valid');
                            break
                    }
                }
                else {
                    position = options.y;
                    vertical = false;
                    switch (options.verticalOrientation) {
                        case'top':
                            inner = 1;
                            break;
                        case'bottom':
                            outer = 1;
                            break;
                        case'middle':
                            inner = outer = 0.5;
                            break;
                        default:
                            self._incidentOccured('The range container is not rendered because the value of the "verticalOrientation" option is not valid');
                            break
                    }
                }
                return inner || outer ? {
                        position: position,
                        vertical: vertical,
                        inner: inner,
                        outer: outer
                    } : null
            },
            _createRange: function(range, settings) {
                var inner = settings.inner,
                    outer = settings.outer,
                    position = settings.position,
                    points;
                if (settings.vertical)
                    points = [position - range.startWidth * inner, range.startPosition, position - range.endWidth * inner, range.endPosition, position + range.endWidth * outer, range.endPosition, position + range.startWidth * outer, range.startPosition];
                else
                    points = [range.startPosition, position + range.startWidth * outer, range.startPosition, position - range.startWidth * inner, range.endPosition, position - range.endWidth * inner, range.endPosition, position + range.endWidth * outer];
                return this._renderer.createArea(points)
            },
            measure: function() {
                var options = this._options,
                    size = options.width || {},
                    result = null;
                size = Number(size) || max(size.start, size.end, 0) || 0;
                if (options.orientation === 'vertical') {
                    result = {
                        min: options.x,
                        max: options.x
                    };
                    switch (options.horizontalOrientation) {
                        case'left':
                            result.min -= size;
                            break;
                        case'right':
                            result.max += size;
                            break;
                        case'center':
                            result.min -= size / 2;
                            result.max += size / 2;
                            break
                    }
                }
                else {
                    result = {
                        min: options.y,
                        max: options.y
                    };
                    switch (options.verticalOrientation) {
                        case'top':
                            result.min -= size;
                            break;
                        case'bottom':
                            result.max += size;
                            break;
                        case'middle':
                            result.min -= size / 2;
                            result.max += size / 2;
                            break
                    }
                }
                return result
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file title.js */
    (function(DX, $, undefined) {
        var Rectangle = DX.viz.core.Rectangle;
        var isString = DX.utils.isString,
            isDefined = DX.utils.isDefined,
            min = Math.min,
            max = Math.max,
            floor = Math.floor,
            ceil = Math.ceil,
            $extend = $.extend;
        DX.viz.gauges.__internals.Title = DX.Class.inherit({
            ctor: function() {
                this._options = {
                    title: {},
                    subtitle: {}
                }
            },
            _measureTexts: function() {
                var self = this,
                    mainBox = self._mainText ? self._mainText.getBBox() : null,
                    subBox = self._subText ? self._subText.getBBox() : null,
                    dy;
                self._location = {
                    x: 0,
                    y: 0
                };
                if (mainBox && subBox) {
                    self._subText.applySettings({y: ceil(-subBox.y)});
                    self._rect = new Rectangle({
                        left: floor(min(mainBox.x, subBox.x)),
                        right: ceil(max(mainBox.x + mainBox.width, subBox.x + subBox.width)),
                        top: floor(mainBox.y),
                        bottom: ceil(subBox.height)
                    })
                }
                else if (mainBox || subBox) {
                    mainBox = mainBox || subBox;
                    self._rect = new Rectangle({
                        left: floor(mainBox.x),
                        right: ceil(mainBox.x + mainBox.width),
                        top: floor(mainBox.y),
                        bottom: ceil(mainBox.y + mainBox.height)
                    })
                }
            },
            render: function(options) {
                var self = this;
                $extend(true, self._options, options);
                self._root = self._root || self._renderer.createGroup({
                    'class': 'dxg-title',
                    align: 'center'
                }).append(self._owner);
                if (isString(self._options.title.text)) {
                    self._mainText = self._mainText || self._renderer.createText().append(self._root);
                    self._mainText.applySettings({
                        x: 0,
                        y: 0,
                        font: self._options.title.font,
                        text: self._options.title.text
                    })
                }
                else {
                    self._mainText && self._mainText.remove();
                    delete self._mainText
                }
                if (isString(self._options.subtitle.text)) {
                    self._subText = self._subText || self._renderer.createText().append(self._root);
                    self._subText.applySettings({
                        x: 0,
                        y: 0,
                        font: self._options.subtitle.font,
                        text: self._options.subtitle.text
                    })
                }
                else {
                    self._subText && self._subText.remove();
                    delete self._subText
                }
                if (self._mainText || self._subText)
                    self._measureTexts();
                else {
                    self._root && self._root.remove();
                    delete self._root
                }
                return self
            },
            processTitleOptions: function(options) {
                if (isString(options))
                    return {text: options};
                else if (!isDefined(options))
                    return {text: null};
                else {
                    options = $extend({}, options);
                    options.layout = $extend({}, options.layout, {position: options.position});
                    return options
                }
            },
            processSubtitleOptions: function(options) {
                if (isString(options))
                    return {text: options};
                else if (!isDefined(options))
                    return {text: null};
                else
                    return $extend({}, options)
            },
            isVisible: function() {
                return !!(this._mainText || this._subText)
            },
            getBoundingRect: function() {
                return this._rect.clone()
            },
            getLayoutOptions: function() {
                return this._options.title.layout || {}
            },
            move: function(dx, dy) {
                var self = this;
                self._root.move(self._location.x += dx, self._location.y += dy);
                self._rect = self._rect.move(dx, dy);
                return self
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file layoutManager.js */
    (function(DX, undefined) {
        var min = Math.min,
            max = Math.max,
            isString = DX.utils.isString;
        var Rectangle = DX.viz.core.Rectangle;
        function parseLayoutOptions(options) {
            options = options || {};
            var parts = (isString(options) ? options : options.position || '').split('-');
            return {
                    primary: isString(parts[0]) ? parts[0].toLowerCase() : '',
                    secondary: isString(parts[1]) ? parts[1].toLowerCase() : '',
                    overlay: options.overlay > 0 ? Number(options.overlay) : 0
                }
        }
        DX.viz.gauges.__internals.LayoutManager = DX.Class.inherit({
            setRect: function(rect) {
                this._rect = rect.clone();
                return this
            },
            getRect: function() {
                return this._rect.clone()
            },
            applyLayout: function(rect, options) {
                var dx = 0,
                    dy = 0,
                    availableRect = this._rect,
                    resultRect = rect.clone(),
                    options_ = parseLayoutOptions(options),
                    delta = resultRect.height() - options_.overlay;
                switch (options_.primary) {
                    case'top':
                        if (delta >= 0) {
                            dy = availableRect.top - resultRect.top;
                            availableRect.top = min(availableRect.top + delta, availableRect.bottom)
                        }
                        else
                            dy = availableRect.top - resultRect.top - delta;
                        break;
                    case'bottom':
                        if (delta >= 0) {
                            dy = availableRect.bottom - resultRect.bottom;
                            availableRect.bottom = max(availableRect.bottom - delta, availableRect.top)
                        }
                        else
                            dy = availableRect.bottom - resultRect.bottom + delta;
                        break
                }
                switch (options_.secondary) {
                    case'':
                    case'center':
                        dx = availableRect.horizontalMiddle() - resultRect.horizontalMiddle();
                        break;
                    case'left':
                        dx = availableRect.left - resultRect.left;
                        break;
                    case'right':
                        dx = availableRect.right - resultRect.right;
                        break
                }
                resultRect = resultRect.move(dx, dy);
                return {
                        rect: resultRect,
                        dx: dx,
                        dy: dy
                    }
            },
            dock: function(rect, options) {
                var dx = 0,
                    dy = 0,
                    mainRect = this._rect,
                    resultRect = rect.clone(),
                    options_ = parseLayoutOptions(options);
                switch (options_.primary) {
                    case'top':
                        dy = mainRect.top - resultRect.bottom + options_.overlay;
                        mainRect.top -= resultRect.height();
                        break;
                    case'bottom':
                        dy = mainRect.bottom - resultRect.top - options_.overlay;
                        mainRect.bottom += resultRect.height();
                        break
                }
                resultRect = resultRect.move(dx, dy);
                return {
                        rect: resultRect,
                        dx: dx,
                        dy: dy
                    }
            },
            selectRectByAspectRatio: function(aspectRatio, margins) {
                var rect = this._rect.clone(),
                    selfAspectRatio,
                    width = 0,
                    height = 0;
                margins = margins || {};
                if (aspectRatio > 0) {
                    rect.left += margins.left || 0;
                    rect.right -= margins.right || 0;
                    rect.top += margins.top || 0;
                    rect.bottom -= margins.bottom || 0;
                    if (rect.width() > 0 && rect.height() > 0) {
                        selfAspectRatio = rect.height() / rect.width();
                        if (selfAspectRatio > 1)
                            aspectRatio < selfAspectRatio ? width = rect.width() : height = rect.height();
                        else
                            aspectRatio > selfAspectRatio ? height = rect.height() : width = rect.width();
                        width > 0 || (width = height / aspectRatio);
                        height > 0 || (height = width * aspectRatio);
                        width = (rect.width() - width) / 2;
                        height = (rect.height() - height) / 2;
                        rect.left += width;
                        rect.right -= width;
                        rect.top += height;
                        rect.bottom -= height
                    }
                    else {
                        rect.left = rect.right = rect.horizontalMiddle();
                        rect.top = rect.bottom = rect.verticalMiddle()
                    }
                }
                return rect
            },
            selectRectBySizes: function(sizes, margins) {
                var rect = this._rect.clone(),
                    step;
                margins = margins || {};
                if (sizes) {
                    rect.left += margins.left || 0;
                    rect.right -= margins.right || 0;
                    rect.top += margins.top || 0;
                    rect.bottom -= margins.bottom || 0;
                    if (sizes.width > 0) {
                        step = (rect.width() - sizes.width) / 2;
                        if (step > 0) {
                            rect.left += step;
                            rect.right -= step
                        }
                    }
                    if (sizes.height > 0) {
                        step = (rect.height() - sizes.height) / 2;
                        if (step > 0) {
                            rect.top += step;
                            rect.bottom -= step
                        }
                    }
                }
                return rect
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file themeManager.js */
    (function(DX, $, undefined) {
        var $extend = $.extend;
        DX.viz.gauges.__internals.ThemeManager = DX.viz.core.BaseThemeManager.inherit({
            ctor: function(options) {
                var self = this;
                options = options || {};
                self.callBase(options.theme, options.path);
                var theme = self.theme;
                $extend(true, theme, {
                    title: {font: {}},
                    subtitle: {font: {}},
                    tooltip: {font: {}},
                    indicator: {text: {font: {}}}
                });
                self.initializeFont(theme.indicator.text.font);
                if (options.path === 'gauge') {
                    $extend(true, theme, {
                        scale: {
                            majorTick: {},
                            minorTick: {},
                            label: {font: {}}
                        },
                        rangeContainer: {},
                        valueIndicator: {rangebar: {text: {font: {}}}},
                        subvalueIndicator: {textcloud: {text: {font: {}}}}
                    });
                    self.initializeFont(theme.scale.label.font);
                    self.initializeFont(theme.valueIndicator.rangebar.text.font);
                    self.initializeFont(theme.subvalueIndicator.textcloud.text.font)
                }
                if (options.path === 'barGauge') {
                    $extend(true, theme, {valueIndicator: {text: {font: {}}}});
                    self.initializeFont(theme.valueIndicator.text.font)
                }
            },
            getPartialTheme: function(part) {
                return this.theme[part] || {}
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file presetManager.js */
    /*! Module viz-gauges, file gauge.js */
    (function(DX, $, undefined) {
        var factory = DX.viz.gauges.__factory;
        var Rectangle = DX.viz.core.Rectangle;
        var isArray = DX.utils.isArray,
            isFunction = DX.utils.isFunction,
            isFinite = window.isFinite,
            Number = window.Number,
            String = window.String,
            setTimeout = window.setTimeout,
            windowResizeCallbacks = DX.utils.windowResizeCallbacks,
            $extend = $.extend,
            $each = $.each,
            $map = $.map;
        var REDRAW_DELAY = 500;
        var OPTION_VALUE = 'value',
            OPTION_SUBVALUES = 'subvalues';
        function noop(){}
        DX.viz.gauges.__internals.BASE_GAUGE_SETTINGS = {
            size: {
                width: undefined,
                height: undefined
            },
            margin: {
                left: 0,
                top: 0,
                right: 0,
                bottom: 0
            },
            animationEnabled: true,
            animationDuration: 1000,
            redrawOnResize: true,
            incidentOccured: noop,
            theme: undefined,
            title: {
                text: undefined,
                layout: {
                    position: 'top-center',
                    overlay: 0
                }
            },
            subtitle: {text: undefined},
            indicator: {
                hasPositiveMeaning: true,
                text: {
                    format: 'fixedPoint',
                    precision: 0,
                    customizeText: $.none,
                    useDefaultColor: false
                },
                layout: {
                    position: 'bottom-center',
                    overlay: 0
                }
            },
            tooltip: {
                enabled: false,
                format: undefined,
                precision: undefined,
                customizeText: undefined,
                horizontalPadding: 22,
                verticalPadding: 6,
                arrowLength: 10
            }
        };
        var DEFAULT_GAUGE_SETTINGS = {
                scale: {
                    majorTick: {
                        visible: true,
                        tickInterval: undefined,
                        length: 5,
                        width: 2,
                        showCalculatedTicks: true,
                        useTicksAutoArrangement: true,
                        customTickValues: []
                    },
                    minorTick: {
                        visible: false,
                        tickInterval: undefined,
                        length: 3,
                        width: 1,
                        showCalculatedTicks: true,
                        customTickValues: []
                    },
                    label: {
                        visible: true,
                        format: undefined,
                        precision: undefined,
                        customizeText: undefined
                    }
                },
                rangeContainer: {
                    offset: 0,
                    width: 5,
                    ranges: []
                },
                valueIndicator: {rangebar: {
                        baseValue: undefined,
                        space: 2,
                        size: 10,
                        text: {
                            indent: 0,
                            customizeText: undefined,
                            format: undefined,
                            precision: undefined
                        }
                    }},
                subvalueIndicator: {
                    trianglemarker: {
                        space: 2,
                        length: 14,
                        width: 13
                    },
                    triangle: {
                        space: 2,
                        length: 14,
                        width: 13
                    },
                    textcloud: {
                        arrowLength: 5,
                        horizontalOffset: 6,
                        verticalOffset: 3,
                        text: {
                            format: undefined,
                            precision: undefined,
                            customizeText: undefined
                        }
                    }
                }
            };
        DX.viz.gauges.Gauge = DX.ui.Component.inherit({
            _THEME_PATH: 'gauge',
            _init: function() {
                var self = this;
                self._initRenderer();
                self._translator = factory.createTranslator(0, 0, 0, 0);
                self._tracker = factory.createTracker({
                    renderer: self._renderer,
                    container: self._rootElement
                });
                self._layoutManager = factory.createLayoutManager();
                self._defaultSettings = self._getDefaultSettings();
                self._mainElements = [];
                self._externalElements = [];
                self._measureElements = [];
                self._initResizeHandler()
            },
            _dispose: function() {
                var self = this;
                self.callBase();
                self._scale && self._scale.dispose() && delete self._scale;
                self._tooltip && self._tooltip.dispose() && delete self._tooltip;
                self._tracker.dispose() && delete self._tracker;
                self._disposeResizeHandler();
                self._disposeRenderer();
                delete self._layoutManager;
                delete self._defaultSettings;
                delete self._mainElements;
                delete self._externalElements;
                delete self._measureElements
            },
            _initRenderer: function() {
                var self = this;
                self._canvas = {
                    width: 1,
                    height: 1,
                    marginLeft: 0,
                    marginRight: 0,
                    marginTop: 0,
                    marginBottom: 0
                };
                self._renderer = factory.createRenderer({
                    width: 1,
                    height: 1
                });
                self._rootElement = self._renderer.getRoot();
                self._rootElement.applySettings({'class': 'dxg ' + self._rootClass})
            },
            _disposeRenderer: function() {
                var self = this;
                self._renderer.killContainer();
                delete self._renderer;
                delete self._canvas;
                self._rootElement.remove();
                delete self._rootElement
            },
            _initResizeHandler: function() {
                var self = this;
                self._resizeHandler = DX.utils.createResizeHandler(function() {
                    self._renderCore()
                });
                self._resizeHandler.dispose = function() {
                    self = null;
                    return this
                }
            },
            _disposeResizeHandler: function() {
                windowResizeCallbacks.remove(this._resizeHandler.stop().dispose());
                delete this._resizeHandler
            },
            _trackWindowResize: function() {
                var self = this,
                    redrawOnResize = self.option('redrawOnResize');
                redrawOnResize = redrawOnResize !== undefined ? !!redrawOnResize : self._defaultSettings.redrawOnResize;
                if (redrawOnResize)
                    windowResizeCallbacks.has(self._resizeHandler) || windowResizeCallbacks.add(self._resizeHandler);
                else
                    windowResizeCallbacks.remove(self._resizeHandler)
            },
            _getDefaultSettings: function() {
                return $extend(true, {}, DX.viz.gauges.__internals.BASE_GAUGE_SETTINGS, DEFAULT_GAUGE_SETTINGS)
            },
            _getIncidentOccured: function() {
                var incidentOccured = this.option('incidentOccured');
                isFunction(incidentOccured) || (incidentOccured = this._defaultSettings.incidentOccured);
                return function() {
                        incidentOccured.apply(null, arguments)
                    }
            },
            _setupAnimationSettings: function() {
                var self = this,
                    enabled = self.option('animationEnabled'),
                    duration = self.option('animationDuration');
                enabled = enabled !== undefined ? !!enabled : self._defaultSettings.animationEnabled;
                duration = duration !== undefined ? Number(duration) : self._defaultSettings.animationDuration;
                self._animationDuration = enabled && duration > 0 ? duration : 0;
                self._animationEnabled = self._animationDuration > 0
            },
            _getDefaultFormatOptions: function() {
                return DX.utils.getAppropriateFormat(this._area.startValue, this._area.endValue, this._getApproximateScreenRange())
            },
            _hide: function() {
                !this._isHidden && (this._isHidden = true) && this._renderer.getRoot().hide()
            },
            _show: function() {
                this._isHidden && delete this._isHidden && this._renderer.getRoot().show()
            },
            _getCanvas: function() {
                var self = this,
                    size = self.option('size') || {},
                    margin = self.option('margin') || {},
                    defaultSize = self._getDefaultContainerSize(),
                    width = size.width >= 0 ? Number(size.width) : self._element().width(),
                    height = size.height >= 0 ? Number(size.height) : self._element().height(),
                    marginLeft = margin.left > 0 ? Number(margin.left) : 0,
                    marginTop = margin.top > 0 ? Number(margin.top) : 0,
                    marginRight = margin.right > 0 ? Number(margin.right) : 0,
                    marginBottom = margin.bottom > 0 ? Number(margin.bottom) : 0;
                if (!width && Number(size.width) !== 0)
                    width = defaultSize.width;
                if (!height && Number(size.height) !== 0)
                    height = defaultSize.height;
                if (marginLeft + marginRight >= width)
                    marginLeft = marginRight = 0;
                if (marginTop + marginBottom >= height)
                    marginTop = marginBottom = 0;
                return {
                        width: width,
                        height: height,
                        marginLeft: marginLeft,
                        marginTop: marginTop,
                        marginRight: marginRight,
                        marginBottom: marginBottom
                    }
            },
            _updateVisibility: function(canvas) {
                var self = this;
                if (canvas.width - canvas.marginLeft - canvas.marginRight >= 2 && canvas.height - canvas.marginTop - canvas.marginBottom >= 2 && self._element().is(':visible')) {
                    self._isRendered && self._show();
                    return true
                }
                else {
                    self._isRendered && self._hide();
                    self._incidentOccured('Gauge cannot be rendered because its container is too small or not visible');
                    return false
                }
            },
            _getArea: function() {
                var self = this,
                    scale = self.option('scale') || {},
                    area = {};
                area.startValue = isFinite(scale.startValue) ? Number(scale.startValue) : 0;
                area.endValue = isFinite(scale.endValue) ? Number(scale.endValue) : 100;
                area.baseValue = Math.min(area.startValue, area.endValue);
                self._setupArea(area);
                self._translator.setup({
                    codomainStart: area.startCoord,
                    codomainEnd: area.endCoord,
                    domainStart: area.startValue,
                    domainEnd: area.endValue
                });
                return area
            },
            _renderTitle: function() {
                var self = this,
                    titleOptions = self.option('title'),
                    subtitleOptions = self.option('subtitle');
                if (!self._title) {
                    self._title = factory.createTitle();
                    self._title._renderer = self._renderer;
                    self._title._owner = self._rootElement
                }
                titleOptions = $extend(true, {}, self._defaultSettings.title, self._themeManager.getPartialTheme('title'), self._title.processTitleOptions(titleOptions));
                subtitleOptions = $extend(true, {}, self._defaultSettings.subtitle, self._themeManager.getPartialTheme('subtitle'), self._title.processSubtitleOptions(subtitleOptions));
                self._title.render({
                    title: titleOptions,
                    subtitle: subtitleOptions
                });
                self._title.isVisible() && self._externalElements.push(self._title)
            },
            _renderDeltaIndicator: function() {
                var self = this,
                    options = self.option('indicator');
                if (!self._indicator) {
                    self._indicator = factory.createIndicator();
                    if (self._indicator) {
                        self._indicator._renderer = self._renderer;
                        self._indicator._owner = self._rootElement
                    }
                }
                if (self._indicator) {
                    options = $extend(true, {}, self._defaultSettings.indicator, self._themeManager.getPartialTheme('indicator'), options);
                    self._indicator.render(options);
                    self._indicator.isVisible() && self._externalElements.push(self._indicator)
                }
            },
            _renderTooltip: function() {
                var self = this,
                    options = $extend(true, {}, self._defaultSettings.tooltip, self._themeManager.getPartialTheme('tooltip'), self.option('tooltip'));
                if (!self._tooltip)
                    self._tooltip = factory.createTooltip({
                        renderer: self._renderer,
                        root: self._root,
                        tracker: self._tracker
                    });
                self._tooltip.init(options).setRect(self._rootRect).render()
            },
            _renderDebugInfo: function() {
                var self = this,
                    group = self._debugGroup || self._renderer.createGroup({'class': 'debug-info'}).append(),
                    rect;
                group.clear();
                rect = self._rootRect;
                self._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#000000',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group);
                rect = self._mainRect;
                self._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#0000FF',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group);
                rect = self._layoutManager.getRect();
                rect && self._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#FF0000',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group);
                rect = self._title && self._title.isVisible() ? self._title.getBoundingRect() : null;
                rect && self._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#00FF00',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group);
                rect = self._indicator && self._indicator.isVisible() ? self._indicator.getBoundingRect() : null;
                rect && self._renderer.createRect(rect.left, rect.top, rect.width(), rect.height(), 0, {
                    stroke: '#00FF00',
                    strokeWidth: 1,
                    fill: 'none'
                }).append(group)
            },
            _renderCore: function(force) {
                var self = this,
                    currentCanvas = self._canvas,
                    canvas = self._getCanvas();
                if (!self._updateVisibility(canvas))
                    return false;
                if (canvas.width === currentCanvas.width && canvas.height === currentCanvas.height && !force)
                    return false;
                self._renderer.container || self._renderer.draw(self._element().get(0));
                self._renderer.resize(canvas.width, canvas.height);
                self._canvas = canvas;
                self._rootRect = new Rectangle({
                    left: canvas.marginLeft,
                    top: canvas.marginTop,
                    right: canvas.width - canvas.marginRight,
                    bottom: canvas.height - canvas.marginBottom
                });
                self._layoutManager.setRect(self._rootRect);
                self._mainRect = self._rootRect.clone();
                self._area = self._getArea();
                self._defaultFormatOptions = self._getDefaultFormatOptions();
                self._mainElements.length = 0;
                self._externalElements.length = 0;
                self._measureElements.length = 0;
                self._renderTitle();
                self._renderDeltaIndicator();
                self._externalElements.reverse();
                $each(self._externalElements, function(_, item) {
                    var layout = self._layoutManager.applyLayout(item.getBoundingRect(), item.getLayoutOptions());
                    item.move(layout.dx, layout.dy)
                });
                self._mainRect = self._layoutManager.getRect();
                self._prepareMainElements();
                $each(self._measureElements, function(_, element) {
                    self._updateElementPosition(element)
                });
                self._applyMainLayout();
                self._renderMainElements();
                $each(self._externalElements, function(_, item) {
                    var layout = self._layoutManager.dock(item.getBoundingRect(), item.getLayoutOptions());
                    item.move(layout.dx, layout.dy)
                });
                self._renderTooltip();
                self._tracker.activate();
                self.option('debugMode') === true && self._renderDebugInfo();
                self._debug_rendered && self._debug_rendered();
                return true
            },
            _updateIndicatorSettings: function(settings) {
                var self = this;
                settings.baseValue = isFinite(self._translator.translate(settings.baseValue)) ? Number(settings.baseValue) : self._area.baseValue;
                settings.currentValue = settings.baseValue;
                if (settings.text && !settings.text.format && !settings.text.precision) {
                    settings.text.format = self._defaultFormatOptions.format;
                    settings.text.precision = self._defaultFormatOptions.precision
                }
            },
            _prepareValueIndicatorSettings: function() {
                var self = this,
                    options = self.option('valueIndicator') || {},
                    defaultOptions = $extend(true, {}, self._defaultSettings.valueIndicator, self._themeManager.getPartialTheme('valueIndicator')),
                    type = String(options.type || defaultOptions.type).toLowerCase();
                self._valueIndicatorSettings = $extend(true, defaultOptions._default, defaultOptions[type], options, {
                    type: type,
                    animationEnabled: self._animationEnabled,
                    animationDuration: self._animationDuration,
                    containerBackgroundColor: self._containerBackgroundColor
                });
                self._updateIndicatorSettings(self._valueIndicatorSettings)
            },
            _prepareSubvalueIndicatorSettings: function() {
                var self = this,
                    options = self.option('subvalueIndicator') || {},
                    defaultOptions = $extend(true, {}, self._defaultSettings.subvalueIndicator, self._themeManager.getPartialTheme('subvalueIndicator')),
                    type = String(options.type || defaultOptions.type).toLowerCase();
                self._subvalueIndicatorSettings = $extend(true, defaultOptions._default, defaultOptions[type], options, {
                    type: type,
                    animationEnabled: self._animationEnabled,
                    animationDuration: self._animationDuration,
                    containerBackgroundColor: self._containerBackgroundColor
                });
                self._updateIndicatorSettings(self._subvalueIndicatorSettings)
            },
            _renderMainElements: function() {
                var self = this;
                self._translator.setup({
                    domainStart: self._area.startValue,
                    domainEnd: self._area.endValue,
                    codomainStart: self._area.startCoord,
                    codomainEnd: self._area.endCoord
                });
                $each(self._mainElements, function(_, element) {
                    self._updateElementPosition(element);
                    element.render()
                })
            },
            _clean: function() {
                this._tracker.deactivate()
            },
            _render: function(parameters) {
                var self = this;
                self._themeManager = factory.createThemeManager({
                    theme: self.option('theme') || self._defaultSettings.theme,
                    path: self._THEME_PATH
                });
                self._incidentOccured = self._getIncidentOccured();
                self._setupAnimationSettings();
                self._containerBackgroundColor = self.option('containerBackgroundColor') || self._themeManager.getPartialTheme('containerBackgroundColor') || self._defaultSettings.containerBackgroundColor;
                if (self._renderCore(true))
                    self._updateActiveElements();
                self._trackWindowResize()
            },
            _prepareMainElements: function() {
                var self = this;
                self._checkForObsoleteMode();
                self._prepareRangeContainer();
                self._prepareScale();
                self._obsoleteMode || self._prepareValueIndicator();
                self._obsoleteMode || self._prepareSubvalueIndicators();
                self._obsoleteMode && self._prepareObsoleteElements()
            },
            _updateActiveElements: function() {
                var self = this;
                if (!self._obsoleteMode) {
                    self._value(self.option(OPTION_VALUE));
                    self._subvalues(self.option(OPTION_SUBVALUES))
                }
                else
                    $each([].concat(self._needles || [], self._markers || [], self._rangeBars || []), function(_, pointer) {
                        pointer.value(pointer._options.value)
                    })
            },
            _prepareScale: function() {
                var self = this,
                    scale = self._scale;
                if (!scale) {
                    scale = self._scale = self._createScale();
                    scale.setup({
                        renderer: self._renderer,
                        translator: self._translator,
                        owner: self._rootElement,
                        incidentOccured: self._incidentOccured
                    })
                }
                scale.init($extend(true, {}, self._defaultSettings.scale, self._themeManager.getPartialTheme('scale'), self.option('scale'), {
                    offset: 0,
                    approximateScreenDelta: self._getApproximateScreenRange()
                }));
                self._mainElements.push(scale);
                self._measureElements.push(scale)
            },
            _prepareRangeContainer: function() {
                var self = this,
                    rangeContainer = self._rangeContainer;
                if (!rangeContainer) {
                    rangeContainer = self._rangeContainer = self._createRangeContainer();
                    rangeContainer.setup({
                        renderer: self._renderer,
                        translator: self._translator,
                        owner: self._rootElement,
                        incidentOccured: self._incidentOccured
                    })
                }
                rangeContainer.init($extend({}, self._defaultSettings.rangeContainer, self._themeManager.getPartialTheme('rangeContainer'), self.option('rangeContainer')));
                self._mainElements.push(rangeContainer);
                self._measureElements.push(rangeContainer)
            },
            _prepareValueIndicator: function() {
                var self = this,
                    indicator = self._valueIndicator,
                    currentValue;
                self._prepareValueIndicatorSettings();
                indicator && self._valueIndicatorType !== self._valueIndicatorSettings.type && indicator.clear() && (indicator = null);
                self._valueIndicatorType = self._valueIndicatorSettings.type;
                if (!indicator) {
                    indicator = self._valueIndicator = self._createValueIndicator(self._valueIndicatorType);
                    if (indicator) {
                        indicator.setup({
                            renderer: self._renderer,
                            translator: self._translator,
                            owner: self._rootElement,
                            tracker: self._tracker,
                            className: 'dxg-value-indicator'
                        });
                        indicator._trackerInfo = {type: 'value-indicator'}
                    }
                    else
                        self._incidentOccured('Value indicator is not created - the "' + self._mainPointerType + '" type is unknown')
                }
                indicator.init(self._valueIndicatorSettings).init({currentValue: indicator.value()});
                self._mainElements.push(indicator);
                self._measureElements.push(indicator)
            },
            _prepareSubvalueIndicators: function() {
                var self = this,
                    subvalueIndicatorsSet = self._subvalueIndicatorsSet;
                if (!subvalueIndicatorsSet)
                    subvalueIndicatorsSet = self._subvalueIndicatorsSet = new DX.viz.gauges.__internals.ValueIndicatorsSet({
                        renderer: self._renderer,
                        translator: self._translator,
                        owner: self._rootElement,
                        tracker: self._tracker,
                        className: 'dxg-subvalue-indicators',
                        indicatorClassName: 'dxg-subvalue-indicator',
                        trackerType: 'subvalue-indicator',
                        createIndicator: function() {
                            return self._createSubvalueIndicator(self._subvalueIndicatorType)
                        }
                    });
                self._prepareSubvalueIndicatorSettings();
                var isRecreate = self._subvalueIndicatorSettings.type !== self._subvalueIndicatorType;
                self._subvalueIndicatorType = self._subvalueIndicatorSettings.type;
                if (self._createSubvalueIndicator(self._subvalueIndicatorType)) {
                    subvalueIndicatorsSet.setSettings(self._subvalueIndicatorSettings, self.option(OPTION_SUBVALUES)).prepare(isRecreate);
                    self._measureElements.push(subvalueIndicatorsSet);
                    self._mainElements.push(subvalueIndicatorsSet)
                }
                else
                    self._incidentOccured('Subvalue indicator is not created - the "' + self._subPointerType + '" type is unknown')
            },
            _value: function(value) {
                var self = this;
                if (arguments.length) {
                    self._valueIndicator.value(value);
                    return self
                }
                return self._valueIndicator.value()
            },
            _subvalues: function(values) {
                var self = this;
                if (arguments.length) {
                    self._subvalueIndicatorsSet.values(values);
                    return self
                }
                return self._subvalueIndicatorsSet.values()
            },
            render: function() {
                this._refresh();
                return this
            },
            value: function(arg) {
                var self = this;
                if (arguments.length) {
                    self._value(arg);
                    self.option(OPTION_VALUE, self._value());
                    return self
                }
                return self._value()
            },
            subvalues: function(arg) {
                var self = this;
                if (arguments.length) {
                    self._subvalues(arg);
                    self.option(OPTION_SUBVALUES, self._subvalues());
                    return self
                }
                return self._subvalues()
            },
            indicatorValue: function(value) {
                var self = this;
                if (value !== undefined)
                    self._indicator && self._indicator.update(value)
            },
            _optionChanged: function(name, newValue, oldValue) {
                var self = this;
                switch (name) {
                    case OPTION_VALUE:
                        self._value(newValue);
                        self.option(OPTION_VALUE, self._value());
                        return null;
                    case OPTION_SUBVALUES:
                        self._subvalues(newValue);
                        self.option(OPTION_SUBVALUES, self._subvalues());
                        return null;
                    default:
                        self._invalidate();
                        return self.callBase.apply(self, arguments)
                }
            },
            _optionValuesEqual: function(name, oldValue, newValue) {
                switch (name) {
                    case OPTION_VALUE:
                        return oldValue === newValue;
                    case OPTION_SUBVALUES:
                        return compareArrays(oldValue, newValue);
                    default:
                        return this.callBase.apply(this, arguments)
                }
            },
            _getDefaultContainerSize: function() {
                throw new Error('_getDefaultContainerSize - not implemented');
            },
            _setupArea: function() {
                throw new Error('_setupArea - not implemented');
            },
            _applyMainLayout: function() {
                throw new Error('_applyMainLayout - not implemented');
            },
            _updateElementPosition: function(element) {
                throw new Error('_updateElementPosition - not implemented');
            },
            _createScale: function() {
                throw new Error('_createScale - not implemented');
            },
            _createRangeContainer: function() {
                throw new Error('_createRangeContainer - not implemented');
            },
            _createValueIndicator: function() {
                throw new Error('_createValueIndicator - not implemented');
            },
            _createSubvalueIndicator: function() {
                throw new Error('_createSubvalueIndicator - not implemented');
            },
            _getApproximateScreenRange: function() {
                throw new Error('_getApproximateScreenRange - not implemented');
            },
            _checkForObsoleteMode: function() {
                var self = this;
                if (self.option(OPTION_VALUE) === undefined && self.option(OPTION_SUBVALUES) === undefined && (self.option('needles') !== undefined || self.option('markers') !== undefined || self.option('rangeBars') !== undefined)) {
                    self._obsoleteMode = true;
                    self._value = noop;
                    self._subvalues = noop;
                    self.value = noop;
                    self.subvalues = noop
                }
                else {
                    delete self._obsoleteMode;
                    delete self._value;
                    delete self._subvalues;
                    delete self.value;
                    delete self.subvalues
                }
            },
            _prepareObsoleteElements: function() {
                var self = this;
                self._prepareObsoletePointers('_rangeBars', '_createRangeBar', {
                    user: self.option('rangeBars'),
                    common: self.option('commonRangeBarSettings'),
                    _default: self._defaultSettings.valueIndicator,
                    theme: self._themeManager.getPartialTheme('valueIndicator'),
                    preset: {},
                    type: 'rangebar',
                    className: 'dxg-value-indicator'
                });
                self._prepareObsoletePointers('_needles', '_createNeedle', {
                    user: self.option('needles'),
                    common: self.option('commonNeedleSettings'),
                    _default: self._defaultSettings.valueIndicator,
                    theme: self._themeManager.getPartialTheme('valueIndicator'),
                    preset: self._getPreset().commonNeedleSettings,
                    className: 'dxg-value-indicator'
                });
                self._prepareObsoletePointers('_markers', '_createMarker', {
                    user: self.option('markers'),
                    common: self.option('commonMarkerSettings'),
                    _default: self._defaultSettings.subvalueIndicator,
                    theme: self._themeManager.getPartialTheme('subvalueIndicator'),
                    preset: self._getPreset().commonMarkerSettings,
                    className: 'dxg-subvalue-indicator'
                })
            },
            _prepareObsoletePointers: function(fieldName, methodName, options) {
                var self = this,
                    userOption = options.user || [],
                    defaultOption = options._default,
                    themeOption = options.theme,
                    presetOption = options.preset,
                    commonOption = options.common || {},
                    parameters = {
                        renderer: self._renderer,
                        owner: self._rootElement,
                        translator: self._translator,
                        tracker: self._tracker,
                        className: options.className
                    },
                    pointers;
                if (isArray(userOption) && userOption.length) {
                    pointers = self[fieldName] = self[fieldName] || [];
                    $each(userOption, function(i, pointerOption) {
                        if (!pointerOption)
                            return;
                        var type = String(pointerOption.type || commonOption.type || presetOption.type || defaultOption.type).toLowerCase(),
                            pointer = pointers[i],
                            currentValue,
                            settings;
                        if (pointer && pointer._options.type !== type) {
                            currentValue = pointer.value();
                            pointer.clear();
                            pointer = null
                        }
                        if (!pointer) {
                            pointer = self[methodName](type);
                            pointer.setup(parameters)
                        }
                        if (pointer) {
                            type = options.type || type;
                            settings = $extend(true, {}, defaultOption._default, defaultOption[type], themeOption._default, themeOption[type], commonOption, pointerOption),
                            delete settings.spindleSize;
                            settings.animationEnabled = self._animationEnabled;
                            settings.animationDuration = self._animationDuration;
                            settings.containerBackgroundColor = self._containerBackgroundColor;
                            self._updateIndicatorSettings(settings);
                            currentValue !== undefined && (settings.currentValue = currentValue);
                            pointer.init(settings);
                            pointers[i] = pointer;
                            self._mainElements.push(pointer);
                            self._measureElements.push(pointer)
                        }
                    })
                }
                else {
                    $each(pointers || [], function(_, pointer) {
                        pointer.clear()
                    });
                    delete self[fieldName]
                }
            },
            needleValue: function(index, value) {
                return accessPointerValue.call(this, this._needles, arguments)
            },
            markerValue: function(index, value) {
                return accessPointerValue.call(this, this._markers, arguments)
            },
            rangeBarValue: function(index, value) {
                return accessPointerValue.call(this, this._rangeBars, arguments)
            }
        }).include(DX.viz.core.loadIndicatorAPI.gauge);
        function accessPointerValue(pointers, args) {
            var pointer = (pointers || [])[args[0]];
            if (args.length > 1) {
                pointer && pointer.value(args[1]);
                return this
            }
            else
                return pointer ? pointer.value() : undefined
        }
        function compareArrays(array1, array2) {
            var i = 0,
                count;
            if (array1 === array2)
                return true;
            if (isArray(array1) && isArray(array2)) {
                count = array1.length;
                if (array2.length === count)
                    for (; i < count; ++i)
                        if (array1[i] !== array2[i])
                            break
            }
            return i === count
        }
        function noop(){}
        DX.viz.gauges.__internals.ValueIndicatorsSet = DX.Class.inherit({
            ctor: function(parameters) {
                var self = this;
                self._parameters = parameters;
                self._createIndicator = self._parameters.createIndicator || noop;
                self._getIndicatorSettings = self._parameters.getIndicatorSettings || noop
            },
            setSettings: function(indicatorSettings, data) {
                var self = this;
                self._indicatorSettings = indicatorSettings;
                self._enabled = data !== null && (isArray(data) || isFinite(data));
                self._options = {offset: indicatorSettings.offset};
                return self
            },
            init: function(indicatorPosition) {
                $extend(true, this._options, indicatorPosition);
                return this
            },
            prepare: function(isRecreate) {
                var self = this;
                if (self._enabled) {
                    self._root = self._root || self._parameters.renderer.createGroup({'class': self._parameters.className});
                    self._root.append(self._parameters.owner);
                    self._indicatorParameters = self._indicatorParameters || {
                        renderer: self._parameters.renderer,
                        translator: self._parameters.translator,
                        owner: self._root,
                        tracker: self._parameters.tracker,
                        className: self._parameters.indicatorClassName
                    };
                    self._indicators = self._indicators || [];
                    if (self._createIndicator())
                        self._indicators = $map(self._indicators, function(indicator, i) {
                            if (isRecreate) {
                                indicator.clear();
                                indicator = self._createIndicator();
                                indicator.setup(self._indicatorParameters);
                                indicator._trackerInfo = {
                                    type: self._parameters.trackerType,
                                    index: i
                                }
                            }
                            indicator.init(self._indicatorSettings).init({currentValue: indicator.value()});
                            return indicator
                        })
                }
                return self
            },
            measure: function() {
                var self = this,
                    indicator = self._createIndicator(),
                    result = null;
                if (indicator && self._enabled) {
                    indicator.setup(self._indicatorParameters).init(self._indicatorSettings).init(self._options);
                    result = indicator.measure();
                    indicator.clear()
                }
                return result
            },
            render: function() {
                var self = this;
                if (self._enabled) {
                    self._root.append(self._parameters.owner);
                    $each(self._indicators, function(i, indicator) {
                        indicator.init(self._options).init(self._getIndicatorSettings(i)).render()
                    })
                }
                else
                    self.clear();
                return self
            },
            clear: function() {
                var self = this;
                if (self._root) {
                    self._root.remove();
                    delete self._root;
                    self._indicators && self._adjustIndicatorsCount(0);
                    delete self._indicators
                }
                return self
            },
            _adjustIndicatorsCount: function(count) {
                var self = this,
                    indicators = self._indicators,
                    i,
                    ii,
                    indicatorOptions,
                    indicator;
                if (indicators.length > count) {
                    for (i = count, ii = indicators.length; i < ii; ++i)
                        indicators[i].clear();
                    self._indicators = indicators.slice(0, count)
                }
                else if (indicators.length < count)
                    for (i = indicators.length, ii = count; i < ii; ++i) {
                        indicator = self._createIndicator();
                        indicator.setup(self._indicatorParameters);
                        indicator._trackerInfo = {
                            type: self._parameters.trackerType,
                            index: i
                        };
                        indicator.init(self._indicatorSettings).init(self._options).init(self._getIndicatorSettings(i)).render();
                        indicators.push(indicator)
                    }
            },
            values: function(arg) {
                var self = this;
                if (!self._enabled)
                    return;
                if (arguments.length) {
                    if (!isArray(arg))
                        arg = isFinite(arg) ? [Number(arg)] : null;
                    if (arg) {
                        self._adjustIndicatorsCount(arg.length);
                        $each(self._indicators, function(i, indicator) {
                            indicator.value(arg[i])
                        })
                    }
                    return self
                }
                return $map(self._indicators, function(indicator) {
                        return indicator.value()
                    })
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file circularGauge.js */
    (function(DX, $, undefined) {
        var factory = DX.viz.gauges.__factory;
        var isFinite = window.isFinite,
            Number = window.Number,
            normalizeAngle = DX.utils.normalizeAngle,
            getCosAndSin = DX.utils.getCosAndSin,
            abs = Math.abs,
            max = Math.max,
            min = Math.min,
            round = Math.round,
            slice = Array.prototype.slice,
            $extend = $.extend,
            $each = $.each;
        var PI = Math.PI;
        var DEFAULT_GAUGE_SETTINGS = {
                geometry: {
                    startAngle: 225,
                    endAngle: -45,
                    totalRadius: undefined
                },
                scale: {
                    orientation: 'outside',
                    label: {indentFromTick: 10}
                },
                rangeContainer: {orientation: 'outside'},
                valueIndicator: {
                    type: 'rectangleneedle',
                    _default: {
                        offset: 20,
                        indentFromCenter: 0,
                        width: 2,
                        spindleSize: 14,
                        spindleGapSize: 10
                    },
                    triangleneedle: {width: 4},
                    triangle: {width: 4},
                    twocolorneedle: {
                        space: 2,
                        secondFraction: 0.4
                    },
                    twocolorrectangle: {
                        space: 2,
                        secondFraction: 0.4
                    },
                    rangebar: {offset: 30}
                },
                subvalueIndicator: {
                    type: 'trianglemarker',
                    trianglemarker: {offset: 6},
                    triangle: {offset: 6},
                    textcloud: {offset: -6}
                }
            };
        function getSides(startAngle, endAngle) {
            var startCosSin = getCosAndSin(startAngle),
                endCosSin = getCosAndSin(endAngle),
                startCos = startCosSin.cos,
                startSin = startCosSin.sin,
                endCos = endCosSin.cos,
                endSin = endCosSin.sin;
            return {
                    left: startSin <= 0 && endSin >= 0 || startSin <= 0 && endSin <= 0 && startCos <= endCos || startSin >= 0 && endSin >= 0 && startCos >= endCos ? -1 : min(startCos, endCos, 0),
                    right: startSin >= 0 && endSin <= 0 || startSin >= 0 && endSin >= 0 && startCos >= endCos || startSin <= 0 && endSin <= 0 && startCos <= endCos ? 1 : max(startCos, endCos, 0),
                    up: startCos <= 0 && endCos >= 0 || startCos <= 0 && endCos <= 0 && startSin >= endSin || startCos >= 0 && endCos >= 0 && startSin <= endSin ? -1 : -max(startSin, endSin, 0),
                    down: startCos >= 0 && endCos <= 0 || startCos >= 0 && endCos >= 0 && startSin <= endSin || startCos <= 0 && endCos <= 0 && startSin >= endSin ? 1 : -min(startSin, endSin, 0)
                }
        }
        DX.viz.gauges.CircularGauge = DX.viz.gauges.Gauge.inherit({
            _rootClass: 'dxg-circular-gauge',
            _getDefaultSettings: function() {
                return $extend(true, this.callBase(), DEFAULT_GAUGE_SETTINGS)
            },
            _setupArea: function(area) {
                var self = this,
                    geometry = self.option('geometry') || {},
                    startAngle = geometry.startAngle,
                    endAngle = geometry.endAngle,
                    centerAngle;
                startAngle = isFinite(startAngle) ? normalizeAngle(startAngle) : self._defaultSettings.geometry.startAngle;
                endAngle = isFinite(endAngle) ? normalizeAngle(endAngle) : self._defaultSettings.geometry.endAngle;
                if (abs(startAngle - endAngle) < 1) {
                    endAngle -= 360;
                    area.sides = {
                        left: -1,
                        up: -1,
                        right: 1,
                        down: 1
                    }
                }
                else {
                    startAngle < endAngle && (endAngle -= 360);
                    area.sides = getSides(startAngle, endAngle)
                }
                area.x = 0;
                area.y = 0;
                area.radius = 100;
                area.startCoord = startAngle;
                area.endCoord = endAngle;
                area.scaleRadius = geometry.scaleRadius > 0 ? Number(geometry.scaleRadius) : self._defaultSettings.geometry.scaleRadius
            },
            _measureMainElements: function() {
                var self = this,
                    maxRadius = 0,
                    minRadius = Infinity,
                    maxHorizontalOffset = 0,
                    maxVerticalOffset = 0,
                    maxInverseHorizontalOffset = 0,
                    maxInverseVerticalOffset = 0;
                $each(self._measureElements, function(_, x) {
                    var bounds = x.measure();
                    if (bounds) {
                        bounds.min > 0 && (minRadius = min(minRadius, bounds.min));
                        bounds.max > 0 && (maxRadius = max(maxRadius, bounds.max));
                        bounds.horizontalOffset > 0 && (maxHorizontalOffset = max(maxHorizontalOffset, bounds.max + bounds.horizontalOffset));
                        bounds.verticalOffset > 0 && (maxVerticalOffset = max(maxVerticalOffset, bounds.max + bounds.verticalOffset));
                        bounds.inverseHorizontalOffset > 0 && (maxInverseHorizontalOffset = max(maxInverseHorizontalOffset, bounds.inverseHorizontalOffset));
                        bounds.inverseVerticalOffset > 0 && (maxInverseVerticalOffset = max(maxInverseVerticalOffset, bounds.inverseVerticalOffset))
                    }
                });
                maxHorizontalOffset = max(maxHorizontalOffset - maxRadius, 0);
                maxVerticalOffset = max(maxVerticalOffset - maxRadius, 0);
                return {
                        minRadius: minRadius,
                        maxRadius: maxRadius,
                        horizontalMargin: maxHorizontalOffset,
                        verticalMargin: maxVerticalOffset,
                        inverseHorizontalMargin: maxInverseHorizontalOffset,
                        inverseVerticalMargin: maxInverseVerticalOffset
                    }
            },
            _applyMainLayout: function() {
                var self = this,
                    measurements = self._measureMainElements(),
                    area = self._area,
                    sides = area.sides,
                    margins = {
                        left: (sides.left < -0.1 ? measurements.horizontalMargin : measurements.inverseHorizontalMargin) || 0,
                        right: (sides.right > 0.1 ? measurements.horizontalMargin : measurements.inverseHorizontalMargin) || 0,
                        top: (sides.up < -0.1 ? measurements.verticalMargin : measurements.inverseVerticalMargin) || 0,
                        bottom: (sides.down > 0.1 ? measurements.verticalMargin : measurements.inverseVerticalMargin) || 0
                    },
                    rect = self._layoutManager.selectRectByAspectRatio((sides.down - sides.up) / (sides.right - sides.left), margins),
                    radius = min(rect.width() / (sides.right - sides.left), rect.height() / (sides.down - sides.up)),
                    x,
                    y;
                var scaler = (measurements.maxRadius - area.radius + area.scaleRadius) / radius;
                if (0 < scaler && scaler < 1) {
                    rect = rect.scale(scaler);
                    radius *= scaler
                }
                radius = radius - measurements.maxRadius + area.radius;
                x = rect.left - rect.width() * sides.left / (sides.right - sides.left);
                y = rect.top - rect.height() * sides.up / (sides.down - sides.up);
                area.x = round(x);
                area.y = round(y);
                area.radius = radius;
                rect.left -= margins.left;
                rect.right += margins.right;
                rect.top -= margins.top;
                rect.bottom += margins.bottom;
                self._layoutManager.setRect(rect)
            },
            _updateElementPosition: function(element) {
                var area = this._area;
                element.init({
                    x: area.x,
                    y: area.y,
                    radius: round(area.radius - Number(element._options.offset) || area.radius)
                })
            },
            _createScale: function() {
                return factory.createCircularScale()
            },
            _createRangeContainer: function() {
                return factory.createCircularRangeContainer()
            },
            _createValueIndicator: function(type) {
                return factory.createCircularValueIndicator(type)
            },
            _createSubvalueIndicator: function(type) {
                return factory.createCircularSubvalueIndicator(type)
            },
            _getApproximateScreenRange: function() {
                var self = this,
                    area = self._area,
                    r = min(self._mainRect.width() / (area.sides.right - area.sides.left), self._mainRect.height() / (area.sides.down - area.sides.up));
                r > area.totalRadius && (r = area.totalRadius);
                r = 0.8 * r;
                return -self._translator.getCodomainRange() * r * PI / 180
            },
            _getDefaultContainerSize: function() {
                return {
                        width: 300,
                        height: 300
                    }
            },
            _getPreset: function() {
                var preset = this.option('preset'),
                    result;
                if (preset === 'preset2')
                    result = {
                        commonNeedleSettings: {type: 'twocolorrectangle'},
                        commonMarkerSettings: {type: 'triangle'}
                    };
                else if (preset === 'preset3')
                    result = {
                        commonNeedleSettings: {type: 'rectangle'},
                        commonMarkerSettings: {type: 'triangle'}
                    };
                else
                    result = {
                        commonNeedleSettings: {type: 'rectangle'},
                        commonMarkerSettings: {type: 'textcloud'}
                    };
                return result
            },
            _createNeedle: function(type) {
                return factory.createCircularNeedle(type)
            },
            _createMarker: function(type) {
                return factory.createCircularMarker(type)
            },
            _createRangeBar: function() {
                return factory.createCircularRangeBar()
            },
            _prepareMainElements: function() {
                this.callBase();
                this._prepareObsoleteSpindle()
            },
            _renderMainElements: function() {
                this.callBase();
                this._renderObsoleteSpindle()
            },
            _prepareObsoleteSpindle: function() {
                var self = this,
                    spindleOption = self.option('spindle') || {},
                    visible = self._needles && ('visible' in spindleOption ? !!spindleOption.visible : true);
                if (visible) {
                    var defaultOption = self._defaultSettings.valueIndicator._default,
                        size = spindleOption.size || defaultOption.spindleSize;
                    visible = size > 0
                }
                if (visible) {
                    var themeOption = self._themeManager.getPartialTheme('valueIndicator')._default,
                        gapSize = spindleOption.gapSize || defaultOption.spindleGapSize,
                        color = spindleOption.color || themeOption.color || defaultOption.color;
                    gapSize = gapSize <= size ? gapSize : size;
                    self._spindle = self._spindle || self._renderer.createGroup({'class': 'dxg-value-indicator'});
                    self._spindleOuter = self._spindleOuter || self._renderer.createCircle(0, 0, 0, {
                        'class': 'dxg-spindle-border',
                        stroke: 'none',
                        strokeWidth: 0
                    }).append(self._spindle);
                    self._spindleInner = self._spindleInner || self._renderer.createCircle(0, 0, 0, {
                        'class': 'dxg-spindle-hole',
                        stroke: 'none',
                        strokeWidth: 0
                    }).append(self._spindle);
                    self._spindleOuter.applySettings({
                        cx: self._area.x,
                        cy: self._area.y,
                        r: size / 2,
                        fill: color
                    });
                    self._spindleInner.applySettings({
                        cx: self._area.x,
                        cy: self._area.y,
                        r: gapSize / 2,
                        fill: self._containerBackgroundColor
                    })
                }
                else {
                    self._spindle && self._spindle.remove();
                    delete self._spindle;
                    delete self._spindleOuter;
                    delete self._spindleInner
                }
            },
            _renderObsoleteSpindle: function() {
                var self = this;
                if (self._spindle) {
                    self._spindleOuter.applySettings({
                        cx: self._area.x,
                        cy: self._area.y
                    });
                    self._spindleInner.applySettings({
                        cx: self._area.x,
                        cy: self._area.y
                    });
                    self._spindle.append(self._rootElement)
                }
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file linearGauge.js */
    (function(DX, $, undefined) {
        var factory = DX.viz.gauges.__factory;
        var max = Math.max,
            min = Math.min,
            round = Math.round,
            slice = Array.prototype.slice,
            $extend = $.extend,
            $each = $.each;
        var DEFAULT_GAUGE_SETTINGS = {
                geometry: {
                    orientation: 'horizontal',
                    totalSize: undefined
                },
                scale: {
                    horizontalOrientation: 'right',
                    verticalOrientation: 'bottom',
                    label: {indentFromTick: -10}
                },
                rangeContainer: {
                    horizontalOrientation: 'right',
                    verticalOrientation: 'bottom'
                },
                valueIndicator: {
                    type: 'rangebar',
                    _default: {
                        offset: 2.5,
                        length: 15,
                        width: 15
                    },
                    rectangle: {width: 10},
                    rangebar: {
                        offset: 10,
                        horizontalOrientation: 'right',
                        verticalOrientation: 'bottom'
                    }
                },
                subvalueIndicator: {
                    type: 'trianglemarker',
                    _default: {
                        offset: -1,
                        horizontalOrientation: 'left',
                        verticalOrientation: 'top'
                    }
                }
            };
        DX.viz.gauges.LinearGauge = DX.viz.gauges.Gauge.inherit({
            _rootClass: 'dxg-linear-gauge',
            _getDefaultSettings: function() {
                return $extend(true, this.callBase(), DEFAULT_GAUGE_SETTINGS)
            },
            _setupArea: function(area) {
                var geometry = this.option('geometry') || {};
                area.vertical = geometry.orientation === 'vertical';
                area.x = 0;
                area.y = 0;
                area.startCoord = -100;
                area.endCoord = 100;
                area.scaleSize = geometry.scaleSize > 0 ? Number(geometry.scaleSize) : this._defaultSettings.geometry.scaleSize
            },
            _measureMainElements: function() {
                var self = this,
                    minBound = 1000,
                    maxBound = 0,
                    indent = 0;
                $each(self._measureElements, function(i, item) {
                    var bounds = item.measure();
                    if (bounds) {
                        maxBound = max(maxBound, bounds.max);
                        minBound = min(minBound, bounds.min);
                        bounds.indent > 0 && (indent = max(indent, bounds.indent))
                    }
                });
                return {
                        minBound: minBound,
                        maxBound: maxBound,
                        indent: indent
                    }
            },
            _applyMainLayout: function() {
                var self = this,
                    measurements = self._measureMainElements(),
                    area = self._area,
                    rect,
                    offset,
                    counterSize = area.scaleSize + 2 * measurements.indent;
                if (area.vertical) {
                    rect = self._layoutManager.selectRectBySizes({
                        width: measurements.maxBound - measurements.minBound,
                        height: counterSize
                    });
                    offset = rect.horizontalMiddle() - (measurements.minBound + measurements.maxBound) / 2;
                    area.startCoord = rect.bottom - measurements.indent;
                    area.endCoord = rect.top + measurements.indent;
                    area.x = round(area.x + offset)
                }
                else {
                    rect = self._layoutManager.selectRectBySizes({
                        height: measurements.maxBound - measurements.minBound,
                        width: counterSize
                    });
                    offset = rect.verticalMiddle() - (measurements.minBound + measurements.maxBound) / 2;
                    area.startCoord = rect.left + measurements.indent;
                    area.endCoord = rect.right - measurements.indent;
                    area.y = round(area.y + offset)
                }
                self._layoutManager.setRect(rect)
            },
            _updateElementPosition: function(element) {
                var area = this._area;
                element.init({
                    x: round(area.x + Number(element._options.offset) || area.x),
                    y: round(area.y + Number(element._options.offset) || area.y),
                    orientation: area.vertical ? 'vertical' : 'horizontal'
                })
            },
            _createScale: function() {
                return factory.createLinearScale()
            },
            _createRangeContainer: function() {
                return factory.createLinearRangeContainer()
            },
            _createValueIndicator: function(type) {
                return factory.createLinearValueIndicator(type)
            },
            _createSubvalueIndicator: function(type) {
                return factory.createLinearSubvalueIndicator(type)
            },
            _getApproximateScreenRange: function() {
                var self = this,
                    area = self._area,
                    s = area.vertical ? self._mainRect.height() : self._mainRect.width();
                s > area.totalSize && (s = area.totalSize);
                s = s * 0.8;
                return s
            },
            _getDefaultContainerSize: function() {
                var geometry = this.option('geometry') || {};
                if (geometry.orientation === 'vertical')
                    return {
                            width: 100,
                            height: 300
                        };
                else
                    return {
                            width: 300,
                            height: 100
                        }
            },
            _getPreset: function() {
                var preset = this.option('preset'),
                    result;
                if (preset === 'preset2')
                    result = {
                        commonNeedleSettings: {type: 'rhombus'},
                        commonMarkerSettings: {type: 'triangle'}
                    };
                else
                    result = {
                        commonNeedleSettings: {type: 'circle'},
                        commonMarkerSettings: {type: 'textcloud'}
                    };
                return result
            },
            _createNeedle: function(type) {
                return factory.createLinearNeedle(type)
            },
            _createMarker: function(type) {
                return factory.createLinearMarker(type)
            },
            _createRangeBar: function() {
                return factory.createLinearRangeBar()
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file circularBarGauge.js */
    (function(DX, $, undefined) {
        var isFinite = window.isFinite,
            Number = window.Number,
            round = Math.round,
            isArray = DX.utils.isArray,
            $extend = $.extend;
        var OPTION_VALUES = 'values';
        var DEFAULT_GAUGE_SETTINGS = {
                geometry: {
                    startAngle: 225,
                    endAngle: -45,
                    totalRadius: undefined
                },
                valueIndicator: {
                    baseValue: undefined,
                    space: 2,
                    size: 10,
                    text: {
                        indent: 16,
                        format: undefined,
                        precision: undefined,
                        customizeText: undefined
                    }
                }
            };
        DX.viz.gauges.CircularBarGauge = DX.viz.gauges.CircularGauge.inherit({
            _THEME_PATH: 'barGauge',
            _getDefaultSettings: function() {
                return $extend(true, {}, DX.viz.gauges.__internals.BASE_GAUGE_SETTINGS, DEFAULT_GAUGE_SETTINGS)
            },
            _setupArea: function(area) {
                this.callBase.apply(this, arguments);
                var options = this.option('valueIndicator') || {};
                area.startValue = isFinite(options.startValue) ? Number(options.startValue) : 0;
                area.endValue = isFinite(options.endValue) ? Number(options.endValue) : 100;
                area.baseValue = Math.min(area.startValue, area.endValue)
            },
            _prepareIndicatorSettings: function() {
                var self = this;
                self._valueIndicatorSettings = $extend(true, {}, self._defaultSettings.valueIndicator, self._themeManager.getPartialTheme('valueIndicator'), self.option('valueIndicator'), {
                    offset: 0,
                    animationEnabled: self._animationEnabled,
                    animationDuration: self._animationDuration
                });
                self._updateIndicatorSettings(self._valueIndicatorSettings);
                self._indicatorPalette = new DX.viz.core.Palette(self._valueIndicatorSettings.palette);
                self._offsetStep = self._valueIndicatorSettings.size + 4;
                if (self._valueIndicatorSettings.text.indent > 0)
                    self._textIndent = Number(self._valueIndicatorSettings.text.indent)
            },
            _getColor: function(i) {
                var palette = this._indicatorPalette;
                palette.currentColor = i % palette.palette.length;
                var color = palette.getNextColor();
                if (!color) {
                    palette.reset();
                    color = palette.getNextColor()
                }
                return color
            },
            _createValueIndicator: function() {
                return DX.viz.gauges.__factory.createCircularRangeBar()
            },
            _prepareMainElements: function() {
                var self = this,
                    indicatorsSet = self._indicatorsSet;
                if (!indicatorsSet)
                    indicatorsSet = self._indicatorsSet = new DX.viz.gauges.__internals.ValueIndicatorsSet({
                        renderer: self._renderer,
                        translator: self._translator,
                        owner: self._pointersGroup,
                        tracker: self._tracker,
                        className: 'bars',
                        trackerType: 'bar',
                        indicatorClassName: 'dxg-value-indicator',
                        createIndicator: function() {
                            return self._createValueIndicator()
                        },
                        getIndicatorSettings: function(i) {
                            var settings = {};
                            settings.radius = round(indicatorsSet._options.radius - self._offsetStep * i),
                            settings.color = self._getColor(i);
                            self._textIndent && (settings.text = {indent: self._textIndent + self._offsetStep * i});
                            return settings
                        }
                    });
                self._prepareIndicatorSettings();
                indicatorsSet.setSettings(self._valueIndicatorSettings, []).prepare();
                self._measureElements.push(indicatorsSet);
                self._mainElements.push(indicatorsSet)
            },
            _updateActiveElements: function() {
                this._values(this.option(OPTION_VALUES))
            },
            _values: function(values) {
                var self = this;
                if (arguments.length) {
                    self._indicatorsSet.values(values);
                    return self
                }
                return self._indicatorsSet.values()
            },
            values: function(arg) {
                var self = this;
                if (arguments.length) {
                    self._values(arg);
                    self.option(OPTION_VALUES, self._values());
                    return self
                }
                return self._values()
            },
            _optionChanged: function(name, newValue, oldValue) {
                var self = this;
                switch (name) {
                    case OPTION_VALUES:
                        self._values(newValue);
                        return null;
                    default:
                        return self.callBase.apply(self, arguments)
                }
            },
            _optionValuesEqual: function(name, oldValue, newValue) {
                var self = this;
                switch (name) {
                    case OPTION_VALUES:
                        return compareArrays(oldValue, newValue);
                    default:
                        return self.callBase.apply(self, arguments)
                }
            },
            _value: null,
            value: null,
            _subvalues: null,
            subvalues: null
        });
        function compareArrays(array1, array2) {
            var i = 0,
                count;
            if (array1 === array2)
                return true;
            if (isArray(array1) && isArray(array2)) {
                count = array1.length;
                if (array2.length === count)
                    for (; i < count; ++i)
                        if (array1[i] !== array2[i])
                            break
            }
            return i === count
        }
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file tooltip.js */
    (function(DX, $, undefined) {
        var formatHelper = DX.formatHelper;
        var _String = window.String,
            _isFunction = DX.utils.isFunction,
            _extend = $.extend;
        DX.viz.gauges.__internals.Tooltip = DX.Class.inherit({
            _innerType: DX.viz.charts.Tooltip,
            ctor: function(parameters) {
                var self = this;
                DX.utils.debug.assertParam(parameters, 'parameters');
                self._container = parameters.container;
                self._tracker = parameters.tracker;
                self._root = parameters.renderer.createGroup({'class': 'dxg-tooltip'});
                self._inner = new self._innerType({renderer: parameters.renderer}, self._root);
                self._inner.draw();
                self._inner.text.applySettings({'class': 'dxg-text'});
                self._options = {};
                var prepareCallback = function(target, info) {
                        return self._prepare(target, info)
                    };
                var showCallback = function() {
                        return self._show()
                    };
                var hideCallback = function() {
                        return self._hide()
                    };
                self._dispose = function() {
                    self = showCallback = hideCallback = prepareCallback = self._dispose = null
                };
                self._tracker.setCallbacks({
                    'tooltip-prepare': prepareCallback,
                    'tooltip-show': showCallback,
                    'tooltip-hide': hideCallback
                })
            },
            dispose: function() {
                var self = this;
                self._dispose();
                self.clear();
                self._root.clear();
                self._root.dispose();
                self._inner.dispose();
                self._root = self._inner = self._container = self._tracker = self._options = null;
                return self
            },
            init: function(options) {
                _extend(true, this._options, options);
                return this
            },
            render: function() {
                var self = this,
                    options = self._options;
                self._root.detach();
                self._inner.update({
                    canvasWidth: self._width,
                    canvasHeight: self._height,
                    arrowLength: options.arrowLength,
                    paddingLeftRight: options.horizontalPadding,
                    paddingTopBottom: options.verticalPadding,
                    color: options.color
                });
                self._inner.text.applySettings({font: options.font});
                self._tracker.setTooltipState(self._options.enabled);
                self._options.enabled && self._root.append(self._container);
                return self
            },
            clear: function() {
                this._root.detach();
                this._tracker.setTooltipState(false);
                return this
            },
            setRect: function(rect) {
                this._width = rect.width();
                this._height = rect.height();
                return this
            },
            _formatValue: function(value, context) {
                var options = this._options,
                    text = formatHelper.format(value, options.format, options.precision);
                if (_isFunction(options.customizeText)) {
                    var target = _extend({
                            value: value,
                            valueText: text
                        }, context);
                    text = options.customizeText.call(target, target);
                    text = text !== null && text !== undefined ? _String(text) : ''
                }
                return text
            },
            _prepare: function(target, info) {
                var parameters = target.getTooltipParameters();
                (parameters.text = this._formatValue(parameters.value, info)) && (this._parameters = parameters);
                this._DEBUG_parameters = parameters;
                return !!parameters.text
            },
            _show: function() {
                var parameters = this._parameters;
                this._parameters = null;
                this._inner.move(parameters.x, parameters.y, parameters.offset, parameters.text, parameters.color);
                this._inner.show();
                this._DEBUG_shown = true
            },
            _hide: function() {
                this._inner.hide();
                this._DEBUG_hidden = true
            }
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file tracker.js */
    (function(DX, $, undefined) {
        var _setTimeout = window.setTimeout,
            _clearTimeout = window.clearTimeout,
            _extend = $.extend,
            _abs = Math.abs;
        var TOOLTIP_SHOW_DELAY = 300,
            TOOLTIP_HIDE_DELAY = 300,
            TOOLTIP_TOUCH_SHOW_DELAY = 400,
            TOOLTIP_TOUCH_HIDE_DELAY = 300;
        DX.viz.gauges.__internals.Tracker = DX.Class.inherit({
            ctor: function(parameters) {
                DX.utils.debug.assertParam(parameters, 'parameters');
                DX.utils.debug.assertParam(parameters.renderer, 'parameters.renderer');
                DX.utils.debug.assertParam(parameters.container, 'parameters.container');
                var self = this;
                self._container = parameters.container;
                self._element = parameters.renderer.createGroup({
                    'class': 'dxg-tracker',
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: '#000000',
                    opacity: 0.0001
                });
                self._showTooltipCallback = function() {
                    self._showTooltipTimeout = null;
                    var target = self._tooltipEvent.target;
                    self._targetEvent = null;
                    if (self._tooltipTarget !== target) {
                        self._tooltipTarget = target;
                        self._callbacks['tooltip-show']()
                    }
                };
                self._hideTooltipCallback = function() {
                    self._hideTooltipTimeout = null;
                    self._targetEvent = null;
                    if (self._tooltipTarget) {
                        self._callbacks['tooltip-hide']();
                        self._tooltipTarget = null
                    }
                };
                self._dispose = function() {
                    self = self._showTooltipCallback = self._hideTooltipCallback = self._dispose = null
                };
                self._DEBUG_showTooltipTimeoutSet = self._DEBUG_showTooltipTimeoutCleared = self._DEBUG_hideTooltipTimeoutSet = self._DEBUG_hideTooltipTimeoutCleared = 0
            },
            dispose: function() {
                var self = this;
                self._dispose();
                self.deactivate();
                self._element.off();
                self._container = self._element = self._context = self._callbacks = null;
                return self
            },
            activate: function() {
                this._element.append(this._container);
                return this
            },
            deactivate: function() {
                this._element.detach();
                this._element.clear();
                return this
            },
            attach: function(element, target, info) {
                element.data({
                    target: target,
                    info: info
                });
                element.append(this._element);
                return this
            },
            detach: function(element) {
                element.detach();
                element.removeData();
                return this
            },
            setTooltipState: function(state) {
                var self = this,
                    data;
                self._element.off(tooltipMouseEvents).off(tooltipTouchEvents);
                if (state) {
                    data = {tracker: self};
                    self._element.on(tooltipMouseEvents, data).on(tooltipTouchEvents, data)
                }
                return self
            },
            setCallbacks: function(callbacks) {
                this._callbacks = callbacks;
                return this
            },
            _showTooltip: function(event, delay) {
                var self = this,
                    data = $(event.target).data();
                if (self._tooltipTarget === event.target || self._callbacks['tooltip-prepare'](data.target, data.info)) {
                    self._hideTooltipTimeout && ++self._DEBUG_hideTooltipTimeoutCleared;
                    _clearTimeout(self._hideTooltipTimeout);
                    self._hideTooltipTimeout = null;
                    _clearTimeout(self._showTooltipTimeout);
                    self._tooltipEvent = event;
                    ++self._DEBUG_showTooltipTimeoutSet;
                    self._showTooltipTimeout = _setTimeout(self._showTooltipCallback, delay)
                }
            },
            _hideTooltip: function(delay) {
                var self = this;
                self._showTooltipTimeout && ++self._DEBUG_showTooltipTimeoutCleared;
                _clearTimeout(self._showTooltipTimeout);
                self._showTooltipTimeout = null;
                _clearTimeout(self._hideTooltipTimeout);
                ++self._DEBUG_hideTooltipTimeoutSet;
                self._hideTooltipTimeout = _setTimeout(self._hideTooltipCallback, delay)
            }
        });
        var tooltipMouseEvents = {
                'mouseover.gauge-tooltip': handleTooltipMouseOver,
                'mouseout.gauge-tooltip': handleTooltipMouseOut
            };
        var tooltipMouseMoveEvents = {'mousemove.gauge-tooltip': handleTooltipMouseMove};
        var tooltipTouchEvents = {'touchstart.gauge-tooltip': handleTooltipTouchStart};
        function handleTooltipMouseOver(event) {
            var tracker = event.data.tracker;
            tracker._x = event.pageX;
            tracker._y = event.pageY;
            tracker._element.off(tooltipMouseMoveEvents).on(tooltipMouseMoveEvents, event.data);
            tracker._showTooltip(event, TOOLTIP_SHOW_DELAY)
        }
        function handleTooltipMouseMove(event) {
            var tracker = event.data.tracker;
            if (tracker._showTooltipTimeout && _abs(event.pageX - tracker._x) > 4 || _abs(event.pageY - tracker._y) > 4) {
                tracker._x = event.pageX;
                tracker._y = event.pageY;
                tracker._showTooltip(event, TOOLTIP_SHOW_DELAY)
            }
        }
        function handleTooltipMouseOut(event) {
            var tracker = event.data.tracker;
            tracker._element.off(tooltipMouseMoveEvents);
            tracker._hideTooltip(TOOLTIP_HIDE_DELAY)
        }
        var active_touch_tooltip_tracker = null;
        DX.viz.gauges.__internals.Tracker._DEBUG_reset = function() {
            active_touch_tooltip_tracker = null
        };
        function handleTooltipTouchStart(event) {
            event.preventDefault();
            var tracker = active_touch_tooltip_tracker;
            if (tracker && tracker !== event.data.tracker)
                tracker._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY);
            tracker = active_touch_tooltip_tracker = event.data.tracker;
            tracker._showTooltip(event, TOOLTIP_TOUCH_SHOW_DELAY);
            tracker._touch = true
        }
        function handleTooltipDocumentTouchStart(event) {
            var tracker = active_touch_tooltip_tracker;
            if (tracker) {
                if (!tracker._touch) {
                    tracker._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY);
                    active_touch_tooltip_tracker = null
                }
                tracker._touch = null
            }
        }
        function handleTooltipDocumentTouchEnd(event) {
            var tracker = active_touch_tooltip_tracker;
            if (tracker)
                if (tracker._showTooltipTimeout) {
                    tracker._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY);
                    active_touch_tooltip_tracker = null
                }
        }
        $(window.document).on({
            'touchstart.gauge-tooltip': handleTooltipDocumentTouchStart,
            'touchend.gauge-tooltip': handleTooltipDocumentTouchEnd
        })
    })(DevExpress, jQuery);
    /*! Module viz-gauges, file dxCircularGauge.js */
    (function(DX, undefined) {
        DX.ui.registerComponent("dxCircularGauge", DX.viz.gauges.CircularGauge);
        DX.ui.registerComponent('dxCircularBarGauge', DX.viz.gauges.CircularBarGauge)
    })(DevExpress);
    /*! Module viz-gauges, file dxLinearGauge.js */
    (function(DX, undefined) {
        DX.ui.registerComponent("dxLinearGauge", DX.viz.gauges.LinearGauge)
    })(DevExpress);
    DevExpress.MOD_VIZ_GAUGES = true
}
if (!DevExpress.MOD_VIZ_RANGESELECTOR) {
    if (!window.DevExpress)
        throw Error('Required module is not referenced: core');
    if (!DevExpress.MOD_VIZ_CORE)
        throw Error('Required module is not referenced: viz-core');
    /*! Module viz-rangeselector, file namespaces.js */
    (function(DevExpress) {
        DevExpress.viz.rangeSelector = {utils: {}}
    })(DevExpress);
    /*! Module viz-rangeselector, file baseVisualElement.js */
    (function(DX) {
        DevExpress.viz.rangeSelector.BaseVisualElement = DX.Class.inherit({
            ctor: function(renderer) {
                this._renderer = renderer;
                this._isDrawn = false
            },
            applyOptions: function(options) {
                this._options = options || {};
                this._applyOptions(this._options)
            },
            _applyOptions: function(options){},
            redraw: function(group) {
                var self = this;
                if (!self._isDrawn) {
                    self._isDrawn = !(self._draw(group || self._group) === false);
                    if (group)
                        self._group = group
                }
                else
                    self._update(group || self._group)
            },
            isDrawn: function() {
                return !!this._isDrawn
            },
            isInitialized: function() {
                return !!this._options
            },
            _draw: function(group){},
            _update: function(group) {
                group.clear();
                this._draw(group)
            }
        })
    })(DevExpress);
    /*! Module viz-rangeselector, file rangeSelector.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = DX.utils,
            dataUtils = DX.data.utils,
            rangeSelectorUtils = rangeSelector.utils,
            ParseUtils = DX.viz.core.ParseUtils,
            formatHelper = DX.formatHelper;
        var REDRAW_DELAY = 100;
        rangeSelector.consts = {
            fontHeightRatio: 0.55,
            emptySliderMarkerText: '. . .'
        };
        rangeSelector.formatValue = function(value, formatOptions) {
            var formatObject = {
                    value: value,
                    valueText: formatHelper.format(value, formatOptions.format, formatOptions.precision)
                };
            return String(formatOptions.customizeText ? formatOptions.customizeText.call(formatObject, formatObject) : formatObject.valueText)
        };
        rangeSelector.RangeSelector = DX.ui.Component.inherit(function() {
            var SCALE_TEXT_SPACING = 5;
            var defaultRangeSelectorOptions = {
                    size: undefined,
                    margin: {
                        left: 0,
                        top: 0,
                        right: 0,
                        bottom: 0
                    },
                    scale: {
                        showCustomBoundaryTicks: true,
                        showMinorTicks: true,
                        startValue: undefined,
                        endValue: undefined,
                        minorTickCount: undefined,
                        minorTickInterval: undefined,
                        majorTickInterval: undefined,
                        useTicksAutoArrangement: true,
                        setTicksAtUnitBeginning: true,
                        minRange: undefined,
                        maxRange: undefined,
                        placeholderHeight: undefined,
                        valueType: undefined,
                        label: {
                            visible: true,
                            format: undefined,
                            precision: undefined,
                            customizeText: undefined
                        },
                        marker: {
                            visible: true,
                            label: {
                                format: undefined,
                                precision: undefined,
                                customizeText: undefined
                            }
                        }
                    },
                    selectedRange: undefined,
                    sliderMarker: {
                        visible: true,
                        format: undefined,
                        precision: undefined,
                        customizeText: undefined,
                        placeholderSize: undefined
                    },
                    behavior: {
                        snapToTicks: true,
                        animationEnabled: true,
                        moveSelectedRangeByClick: true,
                        manualRangeSelectionEnabled: true,
                        allowSlidersSwap: true,
                        callSelectedRangeChanged: "onMovingComplete"
                    },
                    background: {
                        color: "#C0BAE1",
                        visible: true,
                        image: {
                            url: undefined,
                            location: 'full'
                        }
                    },
                    chart: {
                        commonSeriesSettings: {
                            type: 'area',
                            label: {visible: false},
                            hoverMode: 'none'
                        },
                        equalBarWidth: true,
                        topIndent: 0.1,
                        bottomIndent: 0,
                        valueAxis: {
                            min: undefined,
                            max: undefined,
                            inverted: false
                        },
                        series: undefined
                    },
                    dataSource: undefined,
                    dataSourceField: 'arg',
                    redrawOnResize: true,
                    theme: undefined,
                    selectedRangeChanged: null,
                    incidentOccured: $.noop
                };
            var calculateMarkerSize = function(renderer, value, sliderMarkerOptions) {
                    var formattedText = value === undefined ? rangeSelector.consts.emptySliderMarkerText : rangeSelector.formatValue(value, sliderMarkerOptions),
                        textBBox = rangeSelectorUtils.getTextBBox(renderer, formattedText, sliderMarkerOptions.font);
                    return {
                            width: Math.ceil(textBBox.width) + 2 * sliderMarkerOptions.padding,
                            height: Math.ceil(textBBox.height * rangeSelector.consts.fontHeightRatio) + 2 * sliderMarkerOptions.padding + sliderMarkerOptions.pointerSize
                        }
                };
            var calculateScaleLabelHalfWidth = function(renderer, value, scaleOptions) {
                    var formattedText = rangeSelector.formatValue(value, scaleOptions.label),
                        textBBox = rangeSelectorUtils.getTextBBox(renderer, formattedText, scaleOptions.label.font);
                    return Math.ceil(textBBox.width / 2)
                };
            var calculateRangeContainerCanvas = function(size, margin, sliderMarkerSpacing) {
                    var canvas = {
                            left: margin.left + sliderMarkerSpacing.left,
                            top: margin.top + sliderMarkerSpacing.top,
                            width: size.width - margin.left - margin.right - sliderMarkerSpacing.left - sliderMarkerSpacing.right,
                            height: size.height - margin.top - margin.bottom - sliderMarkerSpacing.top - sliderMarkerSpacing.bottom
                        };
                    if (canvas.width <= 0)
                        canvas.width = 1;
                    return canvas
                };
            var parseSliderMarkersPlaceholderSize = function(placeholderSize) {
                    var placeholderWidthLeft,
                        placeholderWidthRight,
                        placeholderHeight;
                    if (utils.isNumber(placeholderSize))
                        placeholderWidthLeft = placeholderWidthRight = placeholderHeight = placeholderSize;
                    else if (placeholderSize) {
                        if (utils.isNumber(placeholderSize.height))
                            placeholderHeight = placeholderSize.height;
                        if (utils.isNumber(placeholderSize.width))
                            placeholderWidthLeft = placeholderWidthRight = placeholderSize.width;
                        else if (placeholderSize.width) {
                            if (utils.isNumber(placeholderSize.width.left))
                                placeholderWidthLeft = placeholderSize.width.left;
                            if (utils.isNumber(placeholderSize.width.right))
                                placeholderWidthRight = placeholderSize.width.right
                        }
                    }
                    return {
                            widthLeft: placeholderWidthLeft,
                            widthRight: placeholderWidthRight,
                            height: placeholderHeight
                        }
                };
            var calculateSliderMarkersSpacing = function(renderer, size, scale, sliderMarkerOptions) {
                    var leftMarkerSize,
                        leftScaleLabelWidth = 0,
                        rightScaleLabelWidth = 0,
                        rightMarkerSize,
                        canvas,
                        placeholderWidthLeft = 0,
                        placeholderWidthRight = 0,
                        placeholderHeight = 0,
                        parsedPlaceholderSize;
                    parsedPlaceholderSize = parseSliderMarkersPlaceholderSize(sliderMarkerOptions.placeholderSize);
                    placeholderWidthLeft = parsedPlaceholderSize.widthLeft || 0;
                    placeholderWidthRight = parsedPlaceholderSize.widthRight || 0;
                    placeholderHeight = parsedPlaceholderSize.height || 0;
                    if (sliderMarkerOptions.visible) {
                        leftMarkerSize = calculateMarkerSize(renderer, scale.startValue, sliderMarkerOptions);
                        if (!placeholderWidthLeft)
                            placeholderWidthLeft = leftMarkerSize.width;
                        rightMarkerSize = calculateMarkerSize(renderer, scale.endValue, sliderMarkerOptions);
                        if (!placeholderWidthRight)
                            placeholderWidthRight = rightMarkerSize.width;
                        if (!placeholderHeight)
                            placeholderHeight = Math.max(leftMarkerSize.height, rightMarkerSize.height)
                    }
                    if (scale.label.visible) {
                        leftScaleLabelWidth = calculateScaleLabelHalfWidth(renderer, scale.startValue, scale);
                        rightScaleLabelWidth = calculateScaleLabelHalfWidth(renderer, scale.endValue, scale)
                    }
                    placeholderWidthLeft = Math.max(placeholderWidthLeft, leftScaleLabelWidth);
                    placeholderWidthRight = Math.max(placeholderWidthRight, rightScaleLabelWidth);
                    return {
                            left: placeholderWidthLeft,
                            right: placeholderWidthRight,
                            top: placeholderHeight,
                            bottom: 0
                        }
                };
            var clearContainer = function(container) {
                    if (container)
                        container.empty()
                };
            var getContainer = function(self) {
                    return self._element()
                };
            var createRangeContainer = function(rangeContainerOptions) {
                    return rangeSelector.rangeSelectorFactory.createRangeContainer(rangeContainerOptions)
                };
            var createTranslator = function(range, canvas) {
                    return rangeSelector.rangeSelectorFactory.createTranslator(range, canvas)
                };
            var createTranslatorCanvas = function(sizeOptions, rangeContainerCanvas, scaleLabelsAreaHeight) {
                    return {
                            left: rangeContainerCanvas.left,
                            top: rangeContainerCanvas.top,
                            right: sizeOptions.width - rangeContainerCanvas.width - rangeContainerCanvas.left,
                            bottom: sizeOptions.height - rangeContainerCanvas.height - rangeContainerCanvas.top + scaleLabelsAreaHeight,
                            width: sizeOptions.width,
                            height: sizeOptions.height
                        }
                };
            var createRenderer = function(self) {
                    var renderer = self.option('renderer');
                    if (renderer)
                        return renderer;
                    renderer = rangeSelector.rangeSelectorFactory.createRenderer();
                    return renderer
                };
            var createThemeManager = function(theme) {
                    return rangeSelector.rangeSelectorFactory.createThemeManager(theme)
                };
            var calculateValueType = function(firstValue, secondValue) {
                    var types = [$.type(firstValue), $.type(secondValue)];
                    $.inArray();
                    return $.inArray('date', types) != -1 ? 'datetime' : $.inArray('number', types) != -1 ? 'numeric' : ''
                };
            var createSeriesDataSource = function(self) {
                    var seriesDataSource,
                        dataSource = self._dataSource && self._dataSource.items(),
                        scaleOptions = self.option('scale'),
                        valueType = scaleOptions.valueType;
                    if (!valueType)
                        valueType = calculateValueType(scaleOptions.startValue, scaleOptions.endValue);
                    if (dataSource || self.option('chart').series)
                        seriesDataSource = new rangeSelector.SeriesDataSource({
                            renderer: self.renderer,
                            dataSource: dataSource,
                            valueType: (valueType || '').toLowerCase(),
                            chart: self.option('chart'),
                            dataSourceField: self.option('dataSourceField'),
                            backgroundColor: self._userBackgroundColor,
                            incidentOccured: self.option('incidentOccured')
                        });
                    return seriesDataSource
                };
            var calculateTranslatorRange = function(self, seriesDataSource, scaleOptions) {
                    var translatorRange,
                        minValue,
                        maxValue,
                        inverted = false,
                        isEqualDates;
                    if (utils.isDefined(scaleOptions.startValue) && utils.isDefined(scaleOptions.endValue)) {
                        inverted = scaleOptions.inverted = scaleOptions.startValue > scaleOptions.endValue;
                        minValue = inverted ? scaleOptions.endValue : scaleOptions.startValue;
                        maxValue = inverted ? scaleOptions.startValue : scaleOptions.endValue
                    }
                    else if (utils.isDefined(scaleOptions.startValue) || utils.isDefined(scaleOptions.endValue)) {
                        minValue = scaleOptions.startValue;
                        maxValue = scaleOptions.endValue
                    }
                    translatorRange = seriesDataSource ? seriesDataSource.getBoundRange() : new DX.viz.charts.Range;
                    isEqualDates = utils.isDate(minValue) && utils.isDate(maxValue) && minValue.getTime() === maxValue.getTime();
                    if (minValue !== maxValue && !isEqualDates) {
                        translatorRange.invertX = inverted;
                        translatorRange.getBoundRange({
                            minX: minValue,
                            maxX: maxValue,
                            minVisibleX: minValue,
                            maxVisibleX: maxValue
                        })
                    }
                    if (!translatorRange.isDefinedX()) {
                        if (isEqualDates)
                            scaleOptions.valueType = 'numeric';
                        translatorRange.setStubDataX(scaleOptions.valueType)
                    }
                    return translatorRange
                };
            var calculateScaleAreaHeight = function(renderer, scaleOptions, visibleMarkers) {
                    var textBBox,
                        visibleLabels = scaleOptions.label.visible;
                    if (scaleOptions.placeholderHeight)
                        return scaleOptions.placeholderHeight;
                    else {
                        textBBox = rangeSelectorUtils.getTextBBox(renderer, '0', scaleOptions.label.font);
                        return (visibleLabels ? scaleOptions.label.topIndent + textBBox.height : 0) + (visibleMarkers ? scaleOptions.marker.topIndent + scaleOptions.marker.separatorHeight : 0)
                    }
                };
            var getTicksInfo = function(self, scaleOptions, translator, screenDelta) {
                    var isEmpty = scaleOptions.isEmpty,
                        tickProvider = rangeSelector.rangeSelectorFactory.getTickProvider(),
                        minorTicksOptions,
                        majorTicksOptions,
                        startValue,
                        endValue,
                        businessRange = translator.getBusinessRange();
                    minorTicksOptions = {
                        tickInterval: isEmpty ? 0 : self.option('scale').minorTickInterval,
                        showCustomBoundaryTicks: scaleOptions.showCustomBoundaryTicks,
                        minorTickCount: scaleOptions.minorTickCount
                    };
                    majorTicksOptions = {
                        textOptions: {
                            align: 'center',
                            font: scaleOptions.label.font
                        },
                        renderer: self.renderer,
                        getText: function(value) {
                            return rangeSelector.formatValue(value, scaleOptions.label)
                        },
                        translator: translator,
                        isStartTickGenerated: !utils.isDefined(self.option('scale').majorTickInterval),
                        tickInterval: scaleOptions.majorTickInterval,
                        textSpacing: SCALE_TEXT_SPACING,
                        setTicksAtUnitBeginning: scaleOptions.setTicksAtUnitBeginning,
                        useTicksAutoArrangement: scaleOptions.useTicksAutoArrangement,
                        hideLabels: isEmpty
                    };
                    startValue = isEmpty ? businessRange.minX : scaleOptions.startValue;
                    endValue = isEmpty ? businessRange.maxX : scaleOptions.endValue;
                    return tickProvider.getFullTicks(startValue, endValue, screenDelta, majorTicksOptions, minorTicksOptions)
                };
            var updateTickIntervals = function(scaleOptions, screenDelta, incidentOccured) {
                    var tickProvider = rangeSelector.rangeSelectorFactory.getTickProvider(),
                        tickIntervals = tickProvider.getTickIntervals(scaleOptions.startValue, scaleOptions.endValue, screenDelta, {
                            tickInterval: scaleOptions.majorTickInterval,
                            incidentOccured: incidentOccured
                        }, {
                            tickInterval: scaleOptions.minorTickInterval,
                            incidentOccured: incidentOccured
                        });
                    scaleOptions.minorTickInterval = tickIntervals.minorTickInterval;
                    scaleOptions.majorTickInterval = tickIntervals.majorTickInterval
                };
            var updateScaleOptions = function(self, seriesDataSource, translatorRange, screenDelta, scaleOptions) {
                    var minVisibleX = utils.isDefined(translatorRange.minVisibleX) ? translatorRange.minVisibleX : translatorRange.minX,
                        maxVisibleX = utils.isDefined(translatorRange.maxVisibleX) ? translatorRange.maxVisibleX : translatorRange.maxX,
                        isEmptyInterval;
                    if (seriesDataSource && !seriesDataSource.isEmpty()) {
                        scaleOptions.startValue = scaleOptions.inverted ? maxVisibleX : minVisibleX;
                        scaleOptions.endValue = scaleOptions.inverted ? minVisibleX : maxVisibleX
                    }
                    isEmptyInterval = utils.isDate(scaleOptions.startValue) && utils.isDate(scaleOptions.endValue) && scaleOptions.startValue.getTime() === scaleOptions.endValue.getTime() || scaleOptions.startValue === scaleOptions.endValue;
                    scaleOptions.isEmpty = !utils.isDefined(scaleOptions.startValue) || !utils.isDefined(scaleOptions.endValue) || isEmptyInterval || scaleOptions.valueType === 'string';
                    if (scaleOptions.isEmpty)
                        scaleOptions.startValue = scaleOptions.endValue = undefined;
                    else {
                        updateTickIntervals(scaleOptions, screenDelta, self.option('incidentOccured'));
                        if (scaleOptions.valueType === 'datetime' && !utils.isDefined(scaleOptions.label.format))
                            if (!scaleOptions.marker.visible)
                                scaleOptions.label.format = formatHelper.getDateFormatByTickInterval(scaleOptions.startValue, scaleOptions.endValue, scaleOptions.majorTickInterval);
                            else
                                scaleOptions.label.format = utils.getDateUnitInterval(scaleOptions.majorTickInterval)
                    }
                };
            var prepareSliderMarkersOptions = function(self, scaleOptions, screenDelta) {
                    var sliderMarkerOptions = $.extend(true, {}, self.option('sliderMarker')),
                        businessInterval;
                    if (!sliderMarkerOptions.format) {
                        if (!self.option('behavior').snapToTicks && utils.isNumber(scaleOptions.startValue)) {
                            businessInterval = Math.abs(scaleOptions.endValue - scaleOptions.startValue);
                            sliderMarkerOptions.format = 'fixedPoint';
                            sliderMarkerOptions.precision = utils.getSignificantDigitPosition(businessInterval / screenDelta)
                        }
                        if (scaleOptions.valueType === 'datetime')
                            if (!scaleOptions.marker.visible) {
                                if (utils.isDefined(scaleOptions.startValue) && utils.isDefined(scaleOptions.endValue))
                                    sliderMarkerOptions.format = formatHelper.getDateFormatByTickInterval(scaleOptions.startValue, scaleOptions.endValue, scaleOptions.minorTickInterval !== 0 ? scaleOptions.minorTickInterval : scaleOptions.majorTickInterval)
                            }
                            else
                                sliderMarkerOptions.format = utils.getDateUnitInterval(utils.isDefined(scaleOptions.minorTickInterval) && scaleOptions.minorTickInterval !== 0 ? scaleOptions.minorTickInterval : scaleOptions.majorTickInterval)
                    }
                    return sliderMarkerOptions
                };
            var showScaleMarkers = function(scaleOptions) {
                    return scaleOptions.valueType == 'datetime' && scaleOptions.marker.visible
                };
            var updateTranslatorRangeInterval = function(translatorRange, scaleOptions) {
                    var intervalX = scaleOptions.minorTickInterval || scaleOptions.majorTickInterval;
                    translatorRange = translatorRange.getBoundRange({intervalX: intervalX})
                };
            var prepareScaleOptions = function(self, seriesDataSource) {
                    var scaleOptions = $.extend(true, {}, self.option('scale')),
                        incidentOccured = self.option('incidentOccured'),
                        parsedValue = 0,
                        parseUtils = new ParseUtils({incidentOccured: incidentOccured}),
                        valueType = parseUtils.correctValueType((scaleOptions.valueType || '').toLowerCase());
                    if (seriesDataSource)
                        valueType = seriesDataSource.getCalculatedValueType() || valueType;
                    if (!valueType)
                        valueType = calculateValueType(scaleOptions.startValue, scaleOptions.endValue) || 'numeric';
                    scaleOptions.valueType = valueType;
                    if (scaleOptions.valueType === 'string') {
                        incidentOccured('The type of the argument values specified in the data source is not supported.');
                        return scaleOptions
                    }
                    var parser = parseUtils.getParser(valueType, 'scale');
                    if (utils.isDefined(scaleOptions.startValue)) {
                        parsedValue = parser(scaleOptions.startValue);
                        if (utils.isDefined(parsedValue))
                            scaleOptions.startValue = parsedValue;
                        else {
                            scaleOptions.startValue = undefined;
                            incidentOccured.call(null, "Cannot parse the value specified as the startValue property of the scale configuration object.")
                        }
                    }
                    if (utils.isDefined(scaleOptions.endValue)) {
                        parsedValue = parser(scaleOptions.endValue);
                        if (utils.isDefined(parsedValue))
                            scaleOptions.endValue = parsedValue;
                        else {
                            scaleOptions.endValue = undefined;
                            incidentOccured.call(null, "Cannot parse the value specified as the endValue field of the \"scale\" configuration object.")
                        }
                    }
                    scaleOptions.parser = parser;
                    return scaleOptions
                };
            var correctSizeOptions = function(self, sizeOptions, scaleOptions) {
                    var size = self.option('size') || {};
                    if (!sizeOptions.height && size.height !== 0)
                        if (scaleOptions.valueType === 'datetime' && scaleOptions.marker.visible !== false)
                            sizeOptions.height = 160;
                        else
                            sizeOptions.height = 120;
                    if (!sizeOptions.width && size.width !== 0)
                        sizeOptions.width = 400
                };
            var applyOptions = function(self) {
                    var rangeContainerCanvas,
                        seriesDataSource,
                        translatorRange,
                        scaleLabelsAreaHeight,
                        sizeOptions,
                        sliderMarkerSpacing,
                        sliderMarkerOptions,
                        selectedRange,
                        $container = self.container,
                        isEmpty;
                    self._isUpdating = true;
                    sizeOptions = calculateSize(self);
                    self._actualSize = sizeOptions;
                    seriesDataSource = createSeriesDataSource(self);
                    self._scaleOptions = prepareScaleOptions(self, seriesDataSource);
                    correctSizeOptions(self, sizeOptions, self._scaleOptions);
                    if (!sizeOptions.width || !sizeOptions.height || !$container.is(':visible')) {
                        self.stopRedraw = true;
                        self.option('incidentOccured')('RangeSelector can not be drawn as container is not visible');
                        return
                    }
                    else
                        self.stopRedraw = false;
                    updateRendererSize(self, sizeOptions);
                    translatorRange = calculateTranslatorRange(self, seriesDataSource, self._scaleOptions);
                    updateScaleOptions(self, seriesDataSource, translatorRange, sizeOptions.width, self._scaleOptions);
                    updateTranslatorRangeInterval(translatorRange, self._scaleOptions);
                    sliderMarkerOptions = prepareSliderMarkersOptions(self, self._scaleOptions, sizeOptions.width);
                    selectedRange = initSelection(self, self._scaleOptions);
                    sliderMarkerSpacing = calculateSliderMarkersSpacing(self.renderer, sizeOptions, self._scaleOptions, sliderMarkerOptions);
                    rangeContainerCanvas = calculateRangeContainerCanvas(sizeOptions, self.option('margin'), sliderMarkerSpacing);
                    scaleLabelsAreaHeight = calculateScaleAreaHeight(self.renderer, self._scaleOptions, showScaleMarkers(self._scaleOptions));
                    self.translator = createTranslator(translatorRange, createTranslatorCanvas(sizeOptions, rangeContainerCanvas, scaleLabelsAreaHeight));
                    self._scaleOptions.ticksInfo = getTicksInfo(self, self._scaleOptions, self.translator, rangeContainerCanvas.width);
                    self._testTicksInfo = self._scaleOptions.ticksInfo;
                    self._selectedRange = selectedRange;
                    if (seriesDataSource)
                        seriesDataSource.adjustSeriesDimensions(self.translator);
                    self.rangeContainer.applyOptions({
                        canvas: rangeContainerCanvas,
                        scaleLabelsAreaHeight: scaleLabelsAreaHeight,
                        sliderMarkerSpacing: sliderMarkerSpacing,
                        translator: self.translator,
                        selectedRange: selectedRange,
                        scale: self._scaleOptions,
                        behavior: self.option('behavior'),
                        background: self.option('background'),
                        chart: self.option('chart'),
                        seriesDataSource: seriesDataSource,
                        sliderMarker: sliderMarkerOptions,
                        sliderHandle: self.option('sliderHandle'),
                        shutter: self.option('shutter'),
                        selectedRangeChanged: createSelectedRangeChangedFunction(self),
                        setSelectedRange: function(selectedRange) {
                            self.setSelectedRange(selectedRange)
                        }
                    });
                    self._isUpdating = false
                };
            var createSelectedRangeChangedFunction = function(self) {
                    return function(selectedRange, blockSelectedRangeChanged) {
                            var selectedRangeChanged = self.option('selectedRangeChanged');
                            self.option('selectedRange', selectedRange);
                            if (selectedRangeChanged && !blockSelectedRangeChanged)
                                selectedRangeChanged(selectedRange)
                        }
                };
            var calculateSize = function(self) {
                    var $container = self.container,
                        size = self.option('size') || {},
                        result = {
                            width: size.width,
                            height: size.height
                        };
                    if ($container) {
                        if (!result.width)
                            result.width = $container.width();
                        if (!result.height)
                            result.height = $container.height()
                    }
                    self.canvas = result;
                    return result
                };
            var updateRendererSize = function(self, size) {
                    var renderer = self.renderer;
                    if (renderer.isInitialized())
                        renderer.getRoot().applySettings({
                            width: size.width,
                            height: size.height
                        });
                    else {
                        renderer.recreateCanvas(size.width, size.height);
                        renderer.draw(self.container[0])
                    }
                };
            var prepareChartThemeOptions = function(self, options) {
                    var chartTheme;
                    if (!self.option('chart').theme && options && options.theme) {
                        chartTheme = options.theme;
                        if (chartTheme) {
                            if (typeof chartTheme === 'object') {
                                chartTheme = chartTheme.chart || {};
                                chartTheme.name = options.theme.name
                            }
                            self.option('chart').theme = chartTheme
                        }
                    }
                };
            var initSelection = function(self, scaleOptions) {
                    var selectedRangeOptions = self.option('selectedRange'),
                        parser = scaleOptions.parser || function() {
                            return null
                        },
                        parseValue = function(value, entity) {
                            var parsedValue,
                                result = scaleOptions[entity];
                            if (utils.isDefined(value))
                                parsedValue = parser(value);
                            if (!utils.isDefined(parsedValue))
                                self.option('incidentOccured').call(null, "Cannot parse the value specified as the " + entity + " field of the \"selectedRange\" configuration object.");
                            else
                                result = parsedValue;
                            return result
                        };
                    if (!selectedRangeOptions)
                        return {
                                startValue: scaleOptions.startValue,
                                endValue: scaleOptions.endValue
                            };
                    else
                        return {
                                startValue: parseValue(selectedRangeOptions.startValue, 'startValue'),
                                endValue: parseValue(selectedRangeOptions.endValue, 'endValue')
                            }
                };
            var _isSizeChanged = function(self) {
                    var actualSize = self._actualSize,
                        newSize = calculateSize(self);
                    return actualSize && (actualSize.width !== newSize.width || actualSize.height !== newSize.height)
                };
            var _resizeHandler = function(self) {
                    return DX.utils.createResizeHandler(function() {
                            if (_isSizeChanged(self))
                                self._render(true)
                        })
                };
            return {
                    isSizeChanged: function() {
                        return _isSizeChanged(this)
                    },
                    _defaultOptions: function() {
                        return defaultRangeSelectorOptions
                    },
                    _dataSourceOptions: function() {
                        return {
                                paginate: false,
                                _preferSync: true
                            }
                    },
                    _init: function() {
                        var self = this;
                        self.container = getContainer(self);
                        clearContainer(self.container);
                        self.renderer = createRenderer(self);
                        self.rangeContainer = createRangeContainer(self.renderer);
                        if (self.option('redrawOnResize') === true)
                            utils.windowResizeCallbacks.add(_resizeHandler(self));
                        if (!$.isFunction(self.option('incidentOccured'))) {
                            utils.debug.assert(false, 'Function should be passed as "info" callback');
                            self.option('incidentOccured', $.noop)
                        }
                        if (self.option('incidentOccured') === $.noop)
                            self.option('incidentOccured', utils.logger.warn);
                        self._reinitDataSource()
                    },
                    _reinitDataSource: function() {
                        this._refreshDataSource()
                    },
                    _initOptions: function(options) {
                        var self = this,
                            themeManager;
                        this._optionsInitializing = true;
                        options = options || {};
                        self._userOptions = $.extend(true, {}, options);
                        themeManager = createThemeManager(options.theme);
                        themeManager.setBackgroundColor(options.containerBackgroundColor);
                        self.option(themeManager.applyRangeSelectorTheme(options));
                        prepareChartThemeOptions(self, options);
                        if (options.background)
                            self._userBackgroundColor = options.background.color
                    },
                    _render: function(isResizing) {
                        this._optionsInitializing = false;
                        var self = this,
                            currentAnimationEnabled,
                            behaviorOptions;
                        applyOptions(self);
                        if (!self.stopRedraw)
                            if (isResizing) {
                                behaviorOptions = self.option('behavior');
                                currentAnimationEnabled = behaviorOptions.animationEnabled;
                                behaviorOptions.animationEnabled = false;
                                self.rangeContainer.redraw();
                                behaviorOptions.animationEnabled = currentAnimationEnabled
                            }
                            else
                                self.rangeContainer.redraw()
                    },
                    _optionChanged: function(name, value, prevValue) {
                        var self = this;
                        if (!this._optionsInitializing)
                            dataUtils.compileSetter(name)(self._userOptions, value, {
                                functionsAsIs: true,
                                merge: true
                            });
                        if (name === "dataSource") {
                            self._reinitDataSource();
                            self._invalidate()
                        }
                        else if (name === "selectedRange")
                            self.setSelectedRange(self.option('selectedRange'));
                        else if (name === "selectedRangeChanged")
                            self.rangeContainer.slidersContainer.selectedRangeChanged = createSelectedRangeChangedFunction(self);
                        else if (name === 'containerBackgroundColor' || name === 'theme') {
                            this._initOptions(self._userOptions);
                            self._invalidate()
                        }
                        else
                            self._invalidate()
                    },
                    _handleDataSourceChanged: function() {
                        var self = this;
                        if (self.renderer.isInitialized())
                            self._render()
                    },
                    getSelectedRange: function() {
                        var self = this;
                        var selectedRange = self.rangeContainer.slidersContainer.getSelectedRange();
                        return {
                                startValue: selectedRange.startValue,
                                endValue: selectedRange.endValue
                            }
                    },
                    setSelectedRange: function(selectedRange) {
                        var self = this;
                        if (self._isUpdating || !selectedRange)
                            return;
                        var oldSelectedRange = self.rangeContainer.slidersContainer.getSelectedRange();
                        if (oldSelectedRange && oldSelectedRange.startValue === selectedRange.startValue && oldSelectedRange.endValue === selectedRange.endValue)
                            return;
                        self.rangeContainer.slidersContainer.setSelectedRange(selectedRange)
                    },
                    resetSelectedRange: function(blockSelectedRangeChanged) {
                        var self = this;
                        self.setSelectedRange({
                            startValue: self._scaleOptions.startValue,
                            endValue: self._scaleOptions.endValue,
                            blockSelectedRangeChanged: blockSelectedRangeChanged
                        })
                    },
                    render: function(isResizing) {
                        this._render(isResizing);
                        return this
                    }
                }
        }()).include(DX.ui.DataHelperMixin).include(DX.viz.core.loadIndicatorAPI.base)
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file rangeContainer.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector;
        rangeSelector.RangeContainer = rangeSelector.BaseVisualElement.inherit(function() {
            var ctor = function(renderer) {
                    this.callBase(renderer);
                    this.slidersContainer = createSlidersContainer(renderer);
                    this.rangeView = createRangeView(renderer);
                    this.scale = createScale(renderer)
                };
            var _applyOptions = function(options) {
                    var self = this,
                        isEmpty = options.scale.isEmpty,
                        viewCanvas = {
                            left: options.canvas.left,
                            top: options.canvas.top,
                            width: options.canvas.width,
                            height: options.canvas.height >= options.scaleLabelsAreaHeight ? options.canvas.height - options.scaleLabelsAreaHeight : 0
                        };
                    self._viewCanvas = viewCanvas;
                    self.slidersContainer.applyOptions({
                        canvas: viewCanvas,
                        translator: options.translator,
                        scale: options.scale,
                        selectedRange: options.selectedRange,
                        sliderMarker: options.sliderMarker,
                        sliderHandle: options.sliderHandle,
                        shutter: options.shutter,
                        behavior: options.behavior,
                        selectedRangeChanged: options.selectedRangeChanged,
                        isEmpty: isEmpty
                    });
                    self.rangeView.applyOptions({
                        canvas: viewCanvas,
                        translator: options.translator,
                        background: options.background,
                        chart: options.chart,
                        seriesDataSource: options.seriesDataSource,
                        behavior: options.behavior,
                        isEmpty: isEmpty
                    });
                    self.scale.applyOptions({
                        canvas: options.canvas,
                        translator: options.translator,
                        scale: options.scale,
                        hideLabels: isEmpty,
                        scaleLabelsAreaHeight: options.scaleLabelsAreaHeight,
                        setSelectedRange: options.setSelectedRange
                    })
                };
            var createSlidersContainer = function(options) {
                    return rangeSelector.rangeSelectorFactory.createSlidersContainer(options)
                };
            var createScale = function(options) {
                    return rangeSelector.rangeSelectorFactory.createScale(options)
                };
            var createRangeView = function(options) {
                    return rangeSelector.rangeSelectorFactory.createRangeView(options)
                };
            var _createClipRectCanvas = function(canvas, sliderMarkerSpacing) {
                    return {
                            left: canvas.left - sliderMarkerSpacing.left,
                            top: canvas.top - sliderMarkerSpacing.top,
                            width: canvas.width + sliderMarkerSpacing.right + sliderMarkerSpacing.left,
                            height: canvas.height + sliderMarkerSpacing.bottom + sliderMarkerSpacing.top
                        }
                };
            var _draw = function() {
                    var self = this,
                        containerGroup,
                        rangeViewGroup,
                        slidersContainerGroup,
                        scaleGroup,
                        trackersGroup,
                        size = self._options.size,
                        clipRectCanvas = _createClipRectCanvas(self._options.canvas, self._options.sliderMarkerSpacing),
                        viewCanvas = self._viewCanvas;
                    self._clipRect = self._renderer.createClipRect(clipRectCanvas.left, clipRectCanvas.top, clipRectCanvas.width, clipRectCanvas.height).append();
                    containerGroup = self._renderer.createGroup({
                        'class': 'rangeContainer',
                        clipId: self._clipRect.id
                    }).append();
                    self._viewClipRect = self._renderer.createClipRect(viewCanvas.left, viewCanvas.top, viewCanvas.width, viewCanvas.height).append();
                    rangeViewGroup = self._renderer.createGroup({
                        'class': 'view',
                        clipId: self._viewClipRect.id
                    });
                    rangeViewGroup.append(containerGroup);
                    self.rangeView.redraw(rangeViewGroup);
                    slidersContainerGroup = self._renderer.createGroup({'class': 'slidersContainer'});
                    slidersContainerGroup.append(containerGroup);
                    self.slidersContainer.redraw(slidersContainerGroup);
                    scaleGroup = self._renderer.createGroup({'class': 'scale'});
                    scaleGroup.append(containerGroup);
                    self.scale.redraw(scaleGroup);
                    trackersGroup = self._renderer.createGroup({'class': 'trackers'});
                    trackersGroup.append(containerGroup);
                    self._trackersGroup = trackersGroup;
                    self.slidersContainer.appendTrackers(trackersGroup)
                };
            var _update = function() {
                    var self = this,
                        clipRectCanvas = _createClipRectCanvas(self._options.canvas, self._options.sliderMarkerSpacing),
                        viewCanvas = self._viewCanvas;
                    self._clipRect.updateRectangle({
                        x: clipRectCanvas.left,
                        y: clipRectCanvas.top,
                        width: clipRectCanvas.width,
                        height: clipRectCanvas.height
                    });
                    self._viewClipRect.updateRectangle({
                        x: viewCanvas.left,
                        y: viewCanvas.top,
                        width: viewCanvas.width,
                        height: viewCanvas.height
                    });
                    self.rangeView.redraw();
                    self.slidersContainer.redraw();
                    self.slidersContainer.appendTrackers(self._trackersGroup);
                    self.scale.redraw()
                };
            var prototypeObject = {
                    createSlidersContainer: createSlidersContainer,
                    createScale: createScale,
                    ctor: ctor,
                    _applyOptions: _applyOptions,
                    _draw: _draw,
                    _update: _update
                };
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file scale.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            formatHelper = DX.formatHelper,
            utils = DX.utils;
        var SCALE_TEXT_SPACING = 5;
        rangeSelector.Scale = rangeSelector.BaseVisualElement.inherit({
            _setupDateUnitInterval: function(scaleOptions) {
                var key,
                    hasObjectSingleField = function(object) {
                        var fieldsCounter = 0;
                        $.each(object, function() {
                            return ++fieldsCounter < 2
                        });
                        return fieldsCounter === 1
                    },
                    millisecTickInterval,
                    majorTickInterval = scaleOptions.ticksInfo.majorTickInterval,
                    majorTicks = scaleOptions.ticksInfo.majorTicks;
                if (scaleOptions.valueType === 'datetime') {
                    if (utils.isObject(majorTickInterval) && !hasObjectSingleField(majorTickInterval))
                        utils.logger.warn('More than one field is specified within the object assigned to the "tickInterval" option. Assign an object with a single field specified (days, hours or a similar one).');
                    if (majorTicks && majorTicks.autoArrangementStep > 1) {
                        if (utils.isString(majorTickInterval))
                            majorTickInterval = utils.getDateIntervalByString(majorTickInterval);
                        for (key in majorTickInterval) {
                            majorTickInterval[key] *= majorTicks.autoArrangementStep;
                            millisecTickInterval = utils.convertDateTickIntervalToMilliseconds(majorTickInterval)
                        }
                        majorTickInterval = utils.convertMillisecondsToDateUnits(millisecTickInterval)
                    }
                    this.dateUnitInterval = utils.getDateUnitInterval(majorTickInterval)
                }
            },
            _prepareDatesDifferences: function(datesDifferences, tickInterval) {
                var deleteDifferent = tickInterval,
                    dateUnitInterval,
                    i;
                if (deleteDifferent === 'week')
                    deleteDifferent = 'day';
                if (deleteDifferent === 'quarter')
                    deleteDifferent = 'month';
                if (datesDifferences[deleteDifferent])
                    for (i = 0; i < utils.dateUnitIntervals.length; i++) {
                        dateUnitInterval = utils.dateUnitIntervals[i];
                        if (datesDifferences[dateUnitInterval]) {
                            datesDifferences[dateUnitInterval] = false;
                            datesDifferences.count--
                        }
                        if (dateUnitInterval === deleteDifferent)
                            break
                    }
            },
            _getMarkerDate: function(date, tickInterval) {
                var markerDate = new Date(date.getTime()),
                    month = 0;
                switch (tickInterval) {
                    case'quarter':
                        month = formatHelper.getFirstQuarterMonth(date.getMonth());
                    case'month':
                        markerDate.setMonth(month);
                    case'week':
                    case'day':
                        markerDate.setDate(1);
                    case'hour':
                        markerDate.setHours(0, 0, 0, 0);
                        break;
                    case'millisecond':
                        markerDate.setMilliseconds(0);
                        break;
                    case'second':
                        markerDate.setSeconds(0, 0);
                        break;
                    case'minute':
                        markerDate.setMinutes(0, 0, 0);
                        break
                }
                return markerDate
            },
            _drawDateMarker: function(date, options) {
                var labelPosX,
                    labelPosY,
                    dateFormated,
                    scaleOptions,
                    textElement;
                if (options.x === null)
                    return;
                scaleOptions = this._options.scale;
                this.lineOptions['class'] = 'dx-range-selector-date-marker';
                this._renderer.createLine(options.x, options.y, options.x, options.y + scaleOptions.marker.separatorHeight, this.lineOptions).append(options.group);
                dateFormated = this._getLabel(date, options.label);
                labelPosX = options.x + scaleOptions.tick.width + scaleOptions.marker.textLeftIndent;
                labelPosY = options.y + scaleOptions.marker.textTopIndent + scaleOptions.label.font.size;
                this.textOptions.align = 'left';
                textElement = this._renderer.createText(dateFormated, labelPosX, labelPosY, this.textOptions).append(options.group);
                return labelPosX + textElement.getBBox().width
            },
            _drawDateMarkers: function(dates, group) {
                var dateMarker,
                    i,
                    datesDifferences,
                    markerDate,
                    posX,
                    prevMarkerRightX = -1;
                if (this._options.scale.valueType !== 'datetime' || !this.visibleMarkers)
                    return;
                var markerDatePositions = [];
                if (dates.length > 1) {
                    for (i = 1; i < dates.length; i++) {
                        datesDifferences = utils.getDatesDifferences(dates[i - 1], dates[i]);
                        this._prepareDatesDifferences(datesDifferences, this.dateUnitInterval);
                        if (datesDifferences.count > 0) {
                            markerDate = this._getMarkerDate(dates[i], this.dateUnitInterval);
                            this.markerDates = this.markerDates || [];
                            this.markerDates.push(markerDate);
                            posX = this.translator.translateX(markerDate);
                            if (posX > prevMarkerRightX) {
                                posX !== null && markerDatePositions.push({
                                    date: markerDate,
                                    posX: posX
                                });
                                prevMarkerRightX = this._drawDateMarker(markerDate, {
                                    group: group,
                                    y: this._options.canvas.top + this._options.canvas.height - this.markersAreaHeight + this._options.scale.marker.topIndent,
                                    x: posX,
                                    label: this._getLabelFormatOptions(formatHelper.getDateFormatByDifferences(datesDifferences))
                                })
                            }
                        }
                    }
                    this._initializeMarkersEvents(markerDatePositions, group)
                }
            },
            _getLabelFormatOptions: function(formatString) {
                if (!utils.isDefined(this._options.scale.marker.label.format))
                    return $.extend({}, this._options.scale.marker.label, {format: formatString});
                return this._options.scale.marker.label
            },
            _calculateRangeByMarkerPosition: function(posX, markerDatePositions, scaleOptions) {
                var selectedRange = {},
                    index,
                    position;
                for (index in markerDatePositions) {
                    position = markerDatePositions[index];
                    if (!scaleOptions.inverted) {
                        if (posX >= position.posX)
                            selectedRange.startValue = position.date;
                        else if (!selectedRange.endValue)
                            selectedRange.endValue = position.date
                    }
                    else if (posX < position.posX)
                        selectedRange.endValue = position.date;
                    else if (!selectedRange.startValue)
                        selectedRange.startValue = position.date
                }
                selectedRange.startValue = selectedRange.startValue || scaleOptions.startValue;
                selectedRange.endValue = selectedRange.endValue || scaleOptions.endValue;
                return selectedRange
            },
            _initializeMarkersEvents: function(markerDatePositions, group) {
                var self = this,
                    markersAreaTop = this._options.canvas.top + this._options.canvas.height - this.markersAreaHeight + this._options.scale.marker.topIndent,
                    markersTracker,
                    svgOffsetLeft,
                    index,
                    posX,
                    selectedRange;
                if (markerDatePositions.length > 0) {
                    markersTracker = self._renderer.createRect(self._options.canvas.left, markersAreaTop, self._options.canvas.width, self._options.scale.marker.separatorHeight, 0, {
                        fill: 'grey',
                        stroke: 'grey',
                        opacity: 0.0001
                    });
                    markersTracker.append(group);
                    markersTracker.on(rangeSelector.events.start, function(e) {
                        svgOffsetLeft = rangeSelector.utils.getRootOffsetLeft(self._renderer);
                        posX = rangeSelector.utils.getEventPageX(e) - svgOffsetLeft;
                        selectedRange = self._calculateRangeByMarkerPosition(posX, markerDatePositions, self._options.scale);
                        self._options.setSelectedRange(selectedRange)
                    });
                    self._markersTracker = markersTracker
                }
            },
            _getLabel: function(value, options) {
                var formatObject = {
                        value: value,
                        valueText: formatHelper.format(value, options.format, options.precision)
                    };
                return String(options.customizeText ? options.customizeText.call(formatObject, formatObject) : formatObject.valueText)
            },
            _drawLabel: function(value, group) {
                var textY = this._options.canvas.top + this._options.canvas.height - this.markersAreaHeight,
                    textElement = this._renderer.createText(this._getLabel(value, this._options.scale.label), this.translator.translateX(value), textY, this.textOptions);
                textElement.append(group);
                this.textElements = this.textElements || [];
                this.textElements.push(textElement)
            },
            _drawTick: function(value, group) {
                this.lineOptions['class'] = 'dx-range-selector-tick';
                var secondY = this._options.canvas.top + this._options.canvas.height - this.scaleLabelsAreaHeight,
                    posX = this.translator.translateX(value),
                    tickElement = this._renderer.createLine(posX, this._options.canvas.top, posX, secondY, this.lineOptions).append(group);
                this.tickElements = this.tickElements || [];
                this.tickElements.push(tickElement)
            },
            _redraw: function(group, isOptimize) {
                var self = this,
                    scaleOptions = self._options.scale,
                    ticksGroup = self._renderer.createGroup(),
                    labelsGroup = self._renderer.createGroup().append(group),
                    majorTicks = scaleOptions.ticksInfo.majorTicks,
                    minorTicks = scaleOptions.ticksInfo.minorTicks,
                    customBoundaryTicks = scaleOptions.ticksInfo.customBoundaryTicks,
                    hideLabels = self._options.hideLabels || majorTicks.hideLabels || !scaleOptions.label.visible,
                    i;
                for (i = 0; i < majorTicks.length; i++) {
                    if (!hideLabels)
                        self._drawLabel(majorTicks[i], labelsGroup);
                    self._drawTick(majorTicks[i], ticksGroup)
                }
                if (scaleOptions.showMinorTicks)
                    for (i = 0; i < minorTicks.length; i++)
                        self._drawTick(minorTicks[i], ticksGroup);
                for (i = 0; i < customBoundaryTicks.length; i++)
                    self._drawTick(customBoundaryTicks[i], ticksGroup);
                ticksGroup.append(group);
                self._drawDateMarkers(majorTicks, labelsGroup)
            },
            _applyOptions: function(options) {
                var scaleOptions = options.scale,
                    labelsAreaHeight;
                this.textOptions = {
                    align: 'center',
                    'class': 'dx-range-selector-scale',
                    font: scaleOptions.label.font,
                    style: {'-webkit-user-select': 'none'}
                };
                this.lineOptions = {
                    strokeWidth: scaleOptions.tick.width,
                    stroke: scaleOptions.tick.color,
                    strokeOpacity: scaleOptions.tick.opacity
                };
                this._setupDateUnitInterval(scaleOptions);
                this.visibleMarkers = scaleOptions.marker.visible === undefined ? true : scaleOptions.marker.visible;
                labelsAreaHeight = scaleOptions.label.visible ? scaleOptions.label.topIndent + scaleOptions.label.font.size : 0;
                this.scaleLabelsAreaHeight = options.scaleLabelsAreaHeight;
                this.markersAreaHeight = this.scaleLabelsAreaHeight - labelsAreaHeight;
                this.translator = options.translator
            },
            _draw: function(group) {
                this._redraw(group, false)
            },
            _update: function(group) {
                var callBase = this.callBase;
                if (this._markersTracker)
                    this._markersTracker.off(rangeSelector.events.start, '**');
                this.callBase = callBase;
                this.callBase(group)
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file rangeFactory.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            renderers = DX.viz.renderers;
        rangeSelector.rangeSelectorFactory = function() {
            return {
                    createRenderer: function(options) {
                        return new renderers.Renderer(options)
                    },
                    createTranslator: function(range, canvas) {
                        return new DX.viz.core.Translator2D(range, canvas)
                    },
                    getTickProvider: function() {
                        return DX.viz.core.tickProvider
                    },
                    createRangeContainer: function(rangeContainerOptions) {
                        return new rangeSelector.RangeContainer(rangeContainerOptions)
                    },
                    createSlidersContainer: function(options) {
                        return new rangeSelector.SlidersContainer(options)
                    },
                    createScale: function(options) {
                        return new rangeSelector.Scale(options)
                    },
                    createSliderMarker: function(options) {
                        return new rangeSelector.SliderMarker(options)
                    },
                    createRangeView: function(options) {
                        return new rangeSelector.RangeView(options)
                    },
                    createThemeManager: function(options) {
                        return new rangeSelector.ThemeManager(options)
                    },
                    createSlider: function(renderer, sliderIndex) {
                        return new rangeSelector.Slider(renderer, sliderIndex)
                    },
                    createSlidersEventsManager: function(renderer, slidersController, processSelectionChanged) {
                        return new rangeSelector.SlidersEventsManager(renderer, slidersController, processSelectionChanged)
                    },
                    createSlidersController: function(sliders) {
                        return new rangeSelector.SlidersController(sliders)
                    }
                }
        }()
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file slidersContainer.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = DX.utils;
        var msPointerEnabled = window.navigator.msPointerEnabled || window.navigator.pointerEnabled;
        var isNumber = DX.utils.isNumber;
        var isDate = DX.utils.isDate;
        var START_VALUE_INDEX = 0,
            END_VALUE_INDEX = 1;
        rangeSelector.SlidersContainer = rangeSelector.BaseVisualElement.inherit(function() {
            var prototypeObject = {
                    getController: function() {
                        return this._controller
                    },
                    _drawAreaTracker: function(group) {
                        var self = this,
                            areaTracker,
                            selectedAreaTracker;
                        areaTracker = self._renderer.createRect(self._options.canvas.left, self._options.canvas.top, self._options.canvas.width, self._options.canvas.height, 0, {
                            fill: 'grey',
                            stroke: 'grey',
                            opacity: 0.0001
                        });
                        areaTracker.append(group);
                        selectedAreaTracker = self._renderer.createRect(self._options.canvas.left, self._options.canvas.top, self._options.canvas.width, self._options.canvas.height, 0, {
                            fill: 'grey',
                            stroke: 'grey',
                            opacity: 0.0001,
                            style: {cursor: 'pointer'}
                        });
                        selectedAreaTracker.append(group);
                        self._controller.setAreaTrackers(areaTracker, selectedAreaTracker)
                    },
                    _processSelectionChanged: function(moving, blockSelectedRangeChanged) {
                        var self = this,
                            equalLastSelectedRange = function(selectedRange) {
                                return selectedRange && self._lastSelectedRange.startValue === selectedRange.startValue && self._lastSelectedRange.endValue === selectedRange.endValue
                            },
                            selectedRange = self.getSelectedRange();
                        if ((!moving || (self._options.behavior.callSelectedRangeChanged || '').toLowerCase() === "onmoving") && self._options.selectedRangeChanged && !equalLastSelectedRange(selectedRange)) {
                            self._updateLastSelectedRange(selectedRange);
                            if (typeof self._options.selectedRangeChanged === 'function')
                                self._options.selectedRangeChanged.call(null, selectedRange, blockSelectedRangeChanged);
                            if (!moving && !equalLastSelectedRange(selectedRange))
                                self.setSelectedRange(selectedRange)
                        }
                    },
                    _updateLastSelectedRange: function(selectedRange) {
                        selectedRange = selectedRange || this._options.selectedRange;
                        this._lastSelectedRange = {
                            startValue: selectedRange.startValue,
                            endValue: selectedRange.endValue
                        }
                    },
                    _createSlider: function(sliderIndex) {
                        return rangeSelector.rangeSelectorFactory.createSlider(this._renderer, sliderIndex)
                    },
                    _createSlidersController: function(sliders) {
                        return rangeSelector.rangeSelectorFactory.createSlidersController(sliders)
                    },
                    _createSlidersEventsManager: function(controller) {
                        var self = this;
                        return rangeSelector.rangeSelectorFactory.createSlidersEventsManager(self._renderer, controller, function(moving) {
                                self._processSelectionChanged(moving)
                            })
                    },
                    ctor: function(renderer) {
                        var self = this,
                            sliders;
                        self.callBase(renderer);
                        sliders = [self._createSlider(START_VALUE_INDEX), self._createSlider(END_VALUE_INDEX)];
                        self._controller = self._createSlidersController(sliders);
                        self._eventsManager = self._createSlidersEventsManager(self._controller);
                        self._lastSelectedRange = {}
                    },
                    getSelectedRange: function() {
                        return this._controller.getSelectedRange()
                    },
                    setSelectedRange: function(selectedRange) {
                        var self = this,
                            scale = self._options.scale,
                            startValue,
                            endValue,
                            currentSelectedRange = self._options.selectedRange;
                        if (selectedRange) {
                            startValue = selectedRange.startValue;
                            endValue = selectedRange.endValue
                        }
                        if (isNumber(scale.startValue) && isNumber(startValue) || isDate(scale.startValue) && isDate(startValue))
                            currentSelectedRange.startValue = startValue;
                        if (isNumber(scale.endValue) && isNumber(endValue) || isDate(scale.endValue) && isDate(endValue))
                            currentSelectedRange.endValue = endValue;
                        self._controller.applySelectedRange(currentSelectedRange);
                        self._controller.applyPosition();
                        self._processSelectionChanged(false, selectedRange && selectedRange.blockSelectedRangeChanged)
                    },
                    appendTrackers: function(group) {
                        this._controller.appendTrackers(group)
                    },
                    _applyOptions: function(options) {
                        var self = this;
                        self._controller.applyOptions({
                            translator: options.translator,
                            canvas: options.canvas,
                            sliderMarker: options.sliderMarker,
                            sliderHandle: options.sliderHandle,
                            shutter: options.shutter,
                            scale: options.scale,
                            behavior: options.behavior
                        });
                        self._eventsManager.applyOptions({behavior: options.behavior})
                    },
                    _draw: function(group) {
                        var self = this,
                            rootElement;
                        if (msPointerEnabled) {
                            rootElement = self._renderer.getRoot();
                            rootElement && (rootElement.element.style.msTouchAction = "pinch-zoom")
                        }
                        self._controller.redraw(group);
                        self._drawAreaTracker(group);
                        self._eventsManager.initialize();
                        self._update()
                    },
                    _update: function() {
                        var self = this,
                            isEmpty = self._options.isEmpty;
                        self._eventsManager.setEnabled(!isEmpty);
                        self._controller.applySelectedRange(isEmpty ? {} : self._options.selectedRange);
                        self._controller.applyPosition(self.isDrawn());
                        self._updateLastSelectedRange();
                        self._controller.redraw()
                    }
                };
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file slidersController.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = DX.utils;
        var START_VALUE_INDEX = 0,
            END_VALUE_INDEX = 1;
        rangeSelector.SlidersController = DX.Class.inherit(function() {
            return {
                    ctor: function(sliders) {
                        this._sliders = sliders;
                        sliders[START_VALUE_INDEX].setAnotherSlider(sliders[END_VALUE_INDEX]);
                        sliders[END_VALUE_INDEX].setAnotherSlider(sliders[START_VALUE_INDEX])
                    },
                    setAreaTrackers: function(areaTracker, selectedAreaTracker) {
                        this._areaTracker = areaTracker;
                        this._selectedAreaTracker = selectedAreaTracker
                    },
                    applyOptions: function(options) {
                        var self = this,
                            values = null;
                        self._options = options;
                        self.getSlider(START_VALUE_INDEX).applyOptions(options);
                        self.getSlider(END_VALUE_INDEX).applyOptions(options);
                        if (options.behavior.snapToTicks) {
                            values = options.scale.ticksInfo.fullTicks;
                            if (values.length > 1 && values[0] > values[values.length - 1])
                                values = values.reverse()
                        }
                        self.getSlider(START_VALUE_INDEX).setAvailableValues(values);
                        self.getSlider(END_VALUE_INDEX).setAvailableValues(values)
                    },
                    processDocking: function(sliderIndex) {
                        var self = this;
                        if (sliderIndex !== undefined)
                            self.getSlider(sliderIndex).processDocking();
                        else {
                            self.getSlider(START_VALUE_INDEX).processDocking();
                            self.getSlider(END_VALUE_INDEX).processDocking()
                        }
                        self.setTrackersCursorStyle('default');
                        self.applyAreaTrackersPosition()
                    },
                    getSelectedRangeInterval: function() {
                        var self = this;
                        return rangeSelector.utils.getInterval(self.getSlider(START_VALUE_INDEX).getValue(), self.getSlider(END_VALUE_INDEX).getValue())
                    },
                    moveSliders: function(postitionDelta, selectedRangeInterval) {
                        var self = this;
                        self.getSlider(START_VALUE_INDEX).setPosition(self.getSlider(START_VALUE_INDEX).getPosition() + postitionDelta, false, selectedRangeInterval);
                        self.applyPosition(true)
                    },
                    moveSlider: function(sliderIndex, fastSwap, position, offsetPosition, startOffsetPosition, startOffsetPositionChangedCallback) {
                        var self = this,
                            slider = self.getSlider(sliderIndex),
                            anotherSlider = slider.getAnotherSlider(),
                            anotherSliderIndex = anotherSlider.getIndex(),
                            doSwap;
                        if (slider.canSwap())
                            if (sliderIndex === START_VALUE_INDEX ? position > anotherSlider.getPosition() : position < anotherSlider.getPosition()) {
                                doSwap = fastSwap;
                                if (!fastSwap)
                                    if (Math.abs(offsetPosition) >= Math.abs(startOffsetPosition) && offsetPosition * startOffsetPosition < 0) {
                                        doSwap = true;
                                        position += 2 * startOffsetPosition;
                                        startOffsetPositionChangedCallback(-startOffsetPosition)
                                    }
                                if (doSwap) {
                                    self.swapSliders();
                                    anotherSlider.applyPosition(true)
                                }
                            }
                        slider.setPosition(position, true);
                        slider.applyPosition(true);
                        self.applyAreaTrackersPosition();
                        self.setTrackersCursorStyle('w-resize')
                    },
                    applySelectedAreaCenterPosition: function(pos) {
                        var self = this,
                            slidersContainerHalfWidth = (self.getSlider(END_VALUE_INDEX).getPosition() - self.getSlider(START_VALUE_INDEX).getPosition()) / 2,
                            selectedRangeInterval = self.getSelectedRangeInterval();
                        self.getSlider(START_VALUE_INDEX).setPosition(pos - slidersContainerHalfWidth, false, selectedRangeInterval);
                        self.applyPosition();
                        self.processDocking()
                    },
                    processManualSelection: function(startPosition, endPosition, eventArgs) {
                        var self = this,
                            animateSliderIndex,
                            movingSliderIndex,
                            positionRange = [Math.min(startPosition, endPosition), Math.max(startPosition, endPosition)];
                        animateSliderIndex = startPosition < endPosition ? START_VALUE_INDEX : END_VALUE_INDEX;
                        movingSliderIndex = startPosition < endPosition ? END_VALUE_INDEX : START_VALUE_INDEX;
                        self.getSlider(movingSliderIndex).setPosition(positionRange[movingSliderIndex]);
                        self.getSlider(animateSliderIndex).setPosition(positionRange[animateSliderIndex]);
                        self.getSlider(movingSliderIndex).setPosition(positionRange[movingSliderIndex], true);
                        self.getSlider(movingSliderIndex).startEventHandler(eventArgs);
                        self.getSlider(animateSliderIndex).processDocking();
                        self.getSlider(movingSliderIndex).applyPosition(true)
                    },
                    applySelectedRange: function(selectedRange) {
                        var self = this,
                            inverted = self._options.scale.inverted;
                        utils.debug.assertParam(selectedRange, 'selectedRange not passed');
                        if (!inverted && selectedRange.startValue > selectedRange.endValue || inverted && selectedRange.startValue < selectedRange.endValue) {
                            self.getSlider(START_VALUE_INDEX).setValue(selectedRange.endValue);
                            self.getSlider(END_VALUE_INDEX).setValue(selectedRange.startValue)
                        }
                        else {
                            self.getSlider(START_VALUE_INDEX).setValue(selectedRange.startValue);
                            self.getSlider(END_VALUE_INDEX).setValue(selectedRange.endValue)
                        }
                    },
                    getSelectedRange: function() {
                        var self = this;
                        return {
                                startValue: self.getSlider(START_VALUE_INDEX).getValue(),
                                endValue: self.getSlider(END_VALUE_INDEX).getValue()
                            }
                    },
                    swapSliders: function() {
                        var self = this;
                        self._sliders.reverse();
                        self.getSlider(START_VALUE_INDEX).changeLocation();
                        self.getSlider(END_VALUE_INDEX).changeLocation()
                    },
                    applyAreaTrackersPosition: function() {
                        var self = this,
                            selectedRange = self.getSelectedRange(),
                            scaleOptions = self._options.scale,
                            width = self.getSlider(END_VALUE_INDEX).getPosition() - self.getSlider(START_VALUE_INDEX).getPosition(),
                            options = {
                                x: self.getSlider(START_VALUE_INDEX).getPosition(),
                                width: width < 0 ? 0 : width,
                                y: self._options.canvas.top,
                                height: self._options.canvas.height,
                                style: {cursor: scaleOptions.endValue - scaleOptions.startValue === selectedRange.endValue - selectedRange.startValue ? 'default' : 'pointer'}
                            };
                        self._selectedAreaTracker.applySettings(options);
                        self._areaTracker.applySettings({
                            x: self._options.canvas.left,
                            width: self._options.canvas.width,
                            y: self._options.canvas.top,
                            height: self._options.canvas.height
                        })
                    },
                    applyPosition: function(disableAnimation) {
                        var self = this;
                        self.getSlider(START_VALUE_INDEX).applyPosition(disableAnimation);
                        self.getSlider(END_VALUE_INDEX).applyPosition(disableAnimation);
                        self.applyAreaTrackersPosition()
                    },
                    redraw: function(group) {
                        var self = this;
                        self.getSlider(START_VALUE_INDEX).redraw(group);
                        self.getSlider(END_VALUE_INDEX).redraw(group)
                    },
                    appendTrackers: function(group) {
                        var self = this;
                        if (self._areaTracker && self._selectedAreaTracker) {
                            self._areaTracker.append(group);
                            self._selectedAreaTracker.append(group)
                        }
                        self.getSlider(START_VALUE_INDEX).appendTrackers(group);
                        self.getSlider(END_VALUE_INDEX).appendTrackers(group)
                    },
                    getSlider: function(sliderIndex) {
                        return this._sliders[sliderIndex]
                    },
                    getAreaTracker: function() {
                        return this._areaTracker
                    },
                    getSelectedAreaTracker: function() {
                        return this._selectedAreaTracker
                    },
                    setTrackersCursorStyle: function(style) {
                        var self = this;
                        self._selectedAreaTracker.applySettings({style: {cursor: style}});
                        self._areaTracker.applySettings({style: {cursor: style}})
                    }
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file slidersEventsManager.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = DX.utils;
        var setEvents = function() {
                var win = window;
                win = DX.viz.rangeSelector.mockWindow || window;
                var touchSupport = "ontouchstart" in win;
                var msPointerEnabled = win.navigator.msPointerEnabled;
                var pointerEnabled = win.navigator.pointerEnabled;
                rangeSelector.events = {
                    start: pointerEnabled ? "pointerdown" : msPointerEnabled ? "MSPointerDown" : touchSupport ? "touchstart mousedown" : "mousedown",
                    move: pointerEnabled ? "pointermove" : msPointerEnabled ? "MSPointerMove" : touchSupport ? "touchmove mousemove" : "mousemove",
                    end: pointerEnabled ? "pointerup pointercancel" : msPointerEnabled ? "MSPointerUp MSPointerCancel" : touchSupport ? "touchend mouseup" : "mouseup"
                }
            };
        setEvents();
        rangeSelector.__setEvents = setEvents;
        var MIN_MANUAL_SELECTING_WIDTH = 10,
            START_VALUE_INDEX = 0,
            END_VALUE_INDEX = 1;
        rangeSelector.SlidersEventsManager = DX.Class.inherit(function() {
            var getRootOffsetLeft = function(self) {
                    return rangeSelector.utils.getRootOffsetLeft(self._renderer)
                };
            var getEventPageX = function(eventArgs) {
                    return rangeSelector.utils.getEventPageX(eventArgs)
                };
            var isLeftButtonPressed = function(event) {
                    var e = event || window.event,
                        originalEvent = e.originalEvent,
                        touches = e.touches,
                        pointerType = originalEvent ? originalEvent.pointerType : false,
                        eventTouches = originalEvent ? originalEvent.touches : false,
                        isIE8LeftClick = e.which === undefined && e.button === 1,
                        isMSPointerLeftClick = originalEvent && pointerType !== undefined && (pointerType === (originalEvent.MSPOINTER_TYPE_TOUCH || 'touch') || pointerType === (originalEvent.MSPOINTER_TYPE_MOUSE || 'mouse') && originalEvent.buttons === 1),
                        isLeftClick = isIE8LeftClick || e.which === 1,
                        isTouches = touches && touches.length > 0 || eventTouches && eventTouches.length > 0;
                    return isLeftClick || isMSPointerLeftClick || isTouches
                };
            var isMultiTouches = function(event) {
                    var originalEvent = event.originalEvent,
                        touches = event.touches,
                        eventTouches = originalEvent ? originalEvent.touches : false;
                    return touches && touches.length > 1 || eventTouches && eventTouches.length > 1 || null
                };
            var isTouchEventArgs = function(e) {
                    return e && e.type && e.type.indexOf('touch') === 0
                };
            var initializeSliderEvents = function(self, sliderIndex) {
                    var renderer = self._renderer,
                        isTouchEvent,
                        slidersController = self._slidersController,
                        processSelectionChanged = self._processSelectionChanged,
                        slider = slidersController.getSlider(sliderIndex),
                        anotherSlider = slider.getAnotherSlider(),
                        fastSwap,
                        startOffsetPosition,
                        splitterMoving;
                    slider.startEventHandler = function(e) {
                        if (!self._enabled || !isLeftButtonPressed(e) || splitterMoving)
                            return;
                        fastSwap = this === slider.getSliderTracker().element;
                        splitterMoving = true;
                        isTouchEvent = isTouchEventArgs(e);
                        startOffsetPosition = getEventPageX(e) - slider.getPosition() - getRootOffsetLeft(self);
                        if (!isMultiTouches(e)) {
                            this.preventedDefault = true;
                            e.stopPropagation();
                            e.preventDefault()
                        }
                    };
                    slider.on(rangeSelector.events.start, slider.startEventHandler);
                    $(document).on(rangeSelector.events.end, function(e) {
                        if (splitterMoving) {
                            splitterMoving = false;
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                    });
                    $(document).on(rangeSelector.events.move, slider.__moveEventHandler = function(e) {
                        var doSwap,
                            pageX,
                            offsetPosition,
                            svgOffsetLeft = getRootOffsetLeft(self),
                            position,
                            sliderIndex = slider.getIndex();
                        if (isTouchEvent !== isTouchEventArgs(e))
                            return;
                        if (!isLeftButtonPressed(e, true) && splitterMoving) {
                            splitterMoving = false;
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                        else if (splitterMoving) {
                            if (!isMultiTouches(e)) {
                                this.preventedDefault = true;
                                e.preventDefault()
                            }
                            pageX = getEventPageX(e);
                            position = pageX - startOffsetPosition - svgOffsetLeft;
                            offsetPosition = pageX - slider.getPosition() - svgOffsetLeft;
                            slidersController.moveSlider(sliderIndex, fastSwap, position, offsetPosition, startOffsetPosition, function(newStartOffsetPosition) {
                                startOffsetPosition = newStartOffsetPosition
                            });
                            processSelectionChanged(true)
                        }
                    })
                };
            var initializeSelectedAreaEvents = function(self) {
                    var renderer = self._renderer,
                        isTouchEvent,
                        slidersController = self._slidersController,
                        processSelectionChanged = self._processSelectionChanged,
                        selectedAreaTracker = slidersController.getSelectedAreaTracker(),
                        selectedAreaMoving = false,
                        offsetStartPosition,
                        selectedRangeInterval;
                    selectedAreaTracker.on(rangeSelector.events.start, function(e) {
                        if (!self._enabled || !isLeftButtonPressed(e) || selectedAreaMoving)
                            return;
                        selectedAreaMoving = true;
                        isTouchEvent = isTouchEventArgs(e);
                        offsetStartPosition = getEventPageX(e) - slidersController.getSlider(START_VALUE_INDEX).getPosition();
                        selectedRangeInterval = slidersController.getSelectedRangeInterval();
                        if (!isMultiTouches(e)) {
                            this.preventedDefault = true;
                            e.stopPropagation();
                            e.preventDefault()
                        }
                    });
                    $(document).on(rangeSelector.events.end, function(e) {
                        if (selectedAreaMoving) {
                            selectedAreaMoving = false;
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                    });
                    $(document).on(rangeSelector.events.move, self.__selectedAreaMoveEventHandler = function(e) {
                        var positionDelta,
                            pageX;
                        if (isTouchEvent !== isTouchEventArgs(e))
                            return;
                        if (selectedAreaMoving && !isLeftButtonPressed(e)) {
                            selectedAreaMoving = false;
                            slidersController.processDocking();
                            processSelectionChanged(false)
                        }
                        if (selectedAreaMoving) {
                            if (!isMultiTouches(e)) {
                                this.preventedDefault = true;
                                e.preventDefault()
                            }
                            pageX = getEventPageX(e);
                            positionDelta = pageX - slidersController.getSlider(START_VALUE_INDEX).getPosition() - offsetStartPosition;
                            slidersController.moveSliders(positionDelta, selectedRangeInterval);
                            processSelectionChanged(true)
                        }
                    })
                };
            var initializeAreaEvents = function(self) {
                    var renderer = self._renderer,
                        isTouchEvent,
                        slidersController = self._slidersController,
                        processSelectionChanged = self._processSelectionChanged,
                        areaTracker = slidersController.getAreaTracker(),
                        unselectedAreaProcessing = false,
                        splitterMoving = false,
                        startPageX;
                    areaTracker.on(rangeSelector.events.start, function(e) {
                        if (!self._enabled || !isLeftButtonPressed(e) || unselectedAreaProcessing)
                            return;
                        unselectedAreaProcessing = true;
                        isTouchEvent = isTouchEventArgs(e);
                        startPageX = getEventPageX(e)
                    });
                    $(document).on(rangeSelector.events.end, function(e) {
                        var pageX;
                        if (unselectedAreaProcessing) {
                            pageX = getEventPageX(e);
                            if (self._options.behavior.moveSelectedRangeByClick && Math.abs(startPageX - pageX) < MIN_MANUAL_SELECTING_WIDTH)
                                slidersController.applySelectedAreaCenterPosition(pageX - getRootOffsetLeft(self));
                            unselectedAreaProcessing = false;
                            processSelectionChanged(false)
                        }
                    });
                    $(document).on(rangeSelector.events.move, self.__areaMoveEventHandler = function(e) {
                        var pageX,
                            startPosition,
                            endPosition,
                            svgOffsetLeft = getRootOffsetLeft(self);
                        if (isTouchEvent !== isTouchEventArgs(e))
                            return;
                        if (unselectedAreaProcessing && !isLeftButtonPressed(e)) {
                            unselectedAreaProcessing = false;
                            processSelectionChanged(false)
                        }
                        if (unselectedAreaProcessing) {
                            pageX = getEventPageX(e);
                            if (self._options.behavior.manualRangeSelectionEnabled && Math.abs(startPageX - pageX) >= MIN_MANUAL_SELECTING_WIDTH) {
                                startPosition = startPageX - svgOffsetLeft;
                                endPosition = pageX - svgOffsetLeft;
                                slidersController.processManualSelection(startPosition, endPosition, e);
                                unselectedAreaProcessing = false;
                                processSelectionChanged(true)
                            }
                        }
                    })
                };
            rangeSelector.getRootOffsetLeft = getRootOffsetLeft;
            return {
                    ctor: function(renderer, slidersController, processSelectionChanged) {
                        this._renderer = renderer;
                        this._slidersController = slidersController;
                        this._processSelectionChanged = processSelectionChanged;
                        this._enabled = true
                    },
                    applyOptions: function(options) {
                        this._options = options
                    },
                    initialize: function() {
                        var self = this;
                        if (!self._renderer.isInitialized())
                            return;
                        initializeSelectedAreaEvents(self);
                        initializeAreaEvents(self);
                        initializeSliderEvents(self, START_VALUE_INDEX);
                        initializeSliderEvents(self, END_VALUE_INDEX)
                    },
                    setEnabled: function(enabled) {
                        this._enabled = enabled
                    }
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file slider.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = DX.utils;
        var touchSupport = "ontouchstart" in window;
        var msPointerEnabled = window.navigator.msPointerEnabled || window.navigator.pointerEnabled;
        var animationOptions = {duration: 250};
        var SPLITTER_WIDTH = 8,
            TOUCH_SPLITTER_WIDTH = 20,
            START_VALUE_INDEX = 0,
            END_VALUE_INDEX = 1;
        rangeSelector.Slider = rangeSelector.BaseVisualElement.inherit(function() {
            return {
                    getText: function() {
                        if (this._marker)
                            return this._marker.getText()
                    },
                    getAvailableValues: function() {
                        return this._values
                    },
                    getShutter: function() {
                        return this._shutter
                    },
                    getMarker: function() {
                        return this._marker
                    },
                    _createSlider: function() {
                        var self = this,
                            sliderHandle,
                            sliderGroup,
                            sliderHandleOptions = self._options.sliderHandle;
                        sliderGroup = self._renderer.createGroup({'class': 'slider'});
                        sliderGroup.applySettings({
                            translateX: self._options.canvas.left,
                            translateY: self._options.canvas.top
                        });
                        sliderHandle = self._renderer.createLine(0, 0, 0, self._options.canvas.height, {
                            'class': 'dx-range-selector-slider',
                            strokeWidth: sliderHandleOptions.width,
                            stroke: sliderHandleOptions.color,
                            strokeOpacity: sliderHandleOptions.opacity
                        });
                        sliderHandle.append(sliderGroup);
                        sliderGroup.setValid = function(correct) {
                            sliderHandle.applySettings({stroke: correct ? self._options.sliderHandle.color : self._options.sliderMarker.invalidRangeColor})
                        };
                        sliderGroup.updateHeight = function() {
                            sliderHandle.applySettings({points: [0, 0, 0, self._options.canvas.height]})
                        };
                        sliderGroup.applyOptions = function(options) {
                            sliderHandle.applySettings(options)
                        };
                        sliderGroup.__line = sliderHandle;
                        return sliderGroup
                    },
                    _createSliderTracker: function() {
                        var self = this,
                            sliderWidth = touchSupport || msPointerEnabled ? TOUCH_SPLITTER_WIDTH : SPLITTER_WIDTH,
                            sliderTracker,
                            sliderTrackerGroup;
                        sliderTracker = self._renderer.createRect(-sliderWidth / 2, 0, sliderWidth, self._options.canvas.height, 0, {
                            fill: 'grey',
                            stroke: 'grey',
                            opacity: 0.0001,
                            style: {cursor: 'w-resize'}
                        });
                        sliderTrackerGroup = self._renderer.createGroup({'class': 'sliderTracker'});
                        sliderTrackerGroup.applySettings({
                            translateX: 0,
                            translateY: self._options.canvas.top
                        });
                        sliderTracker.append(sliderTrackerGroup);
                        sliderTrackerGroup.updateHeight = function() {
                            sliderTracker.applySettings({height: self._options.canvas.height})
                        };
                        sliderTrackerGroup.__rect = sliderTracker;
                        return sliderTrackerGroup
                    },
                    _drawSliderTracker: function(group) {
                        var self = this,
                            sliderTracker = self._createSliderTracker();
                        if (sliderTracker) {
                            sliderTracker.append(group);
                            self._sliderTracker = sliderTracker
                        }
                    },
                    _createSliderMarker: function(options) {
                        return rangeSelector.rangeSelectorFactory.createSliderMarker(options)
                    },
                    _setPosition: function(position, correctByMinMaxRange) {
                        var self = this,
                            correctedPosition = self._correctPosition(position),
                            value = self._options.translator.untranslateX(correctedPosition);
                        self.setValue(value, correctByMinMaxRange);
                        self._position = correctedPosition
                    },
                    _setPositionForBothSliders: function(startPosition, interval) {
                        var self = this,
                            anotherSlider,
                            startValue,
                            endValue,
                            endPosition,
                            inverted = self._options.scale.inverted;
                        anotherSlider = self.getAnotherSlider();
                        startPosition = self._correctBounds(startPosition);
                        startValue = self._options.translator.untranslateX(startPosition);
                        endValue = utils.addInterval(startValue, interval);
                        if (!inverted && endValue > self._options.scale.endValue || inverted && endValue < self._options.scale.endValue) {
                            endValue = self._options.scale.endValue;
                            endPosition = self._options.canvas.left + self._options.canvas.width;
                            startValue = utils.addInterval(endValue, interval, true);
                            startPosition = self._options.translator.translateX(startValue)
                        }
                        else
                            endPosition = self._options.translator.translateX(endValue);
                        if (self._values)
                            if (!inverted ? startValue < self._values[0] : startValue > self._values[self._values.length - 1]) {
                                startValue = self._correctBusinessValueByAvailableValues(startValue);
                                endValue = utils.addInterval(startValue, interval)
                            }
                            else {
                                endValue = self._correctBusinessValueByAvailableValues(endValue);
                                startValue = utils.addInterval(endValue, interval, true)
                            }
                        anotherSlider.setValue(endValue);
                        self.setValue(startValue);
                        self._position = startPosition;
                        anotherSlider._position = endPosition
                    },
                    _correctPosition: function(position) {
                        var self = this,
                            correctedPosition = self._correctInversion(position);
                        correctedPosition = self._correctBounds(correctedPosition);
                        return correctedPosition
                    },
                    _correctInversion: function(position) {
                        var self = this,
                            correctedPosition = position,
                            anotherSliderPosition = self.getAnotherSlider().getPosition(),
                            slidersInverted = self.getIndex() === START_VALUE_INDEX ? position > anotherSliderPosition : position < anotherSliderPosition;
                        if (slidersInverted)
                            correctedPosition = anotherSliderPosition;
                        return correctedPosition
                    },
                    _correctBounds: function(position) {
                        var self = this,
                            correctedPosition = position,
                            canvas = self._options.canvas;
                        if (position < canvas.left)
                            correctedPosition = canvas.left;
                        if (position > canvas.left + canvas.width)
                            correctedPosition = canvas.left + canvas.width;
                        return correctedPosition
                    },
                    _correctBusinessValue: function(businessValue, correctByMinMaxRange) {
                        var self = this,
                            result = self._correctBusinessValueByAvailableValues(businessValue);
                        if (correctByMinMaxRange)
                            result = self._correctBusinessValueByMinMaxRangeFromAnotherSlider(result);
                        result = self._correctBusinessValueByMinRangeFromStartEndValues(result);
                        return result
                    },
                    _correctBusinessValueByAvailableValues: function(businessValue) {
                        var values = this._values;
                        if (values)
                            return rangeSelector.utils.findNearValue(values, businessValue);
                        return businessValue
                    },
                    _correctBusinessValueByMinMaxRangeFromAnotherSlider: function(businessValue) {
                        var self = this,
                            result = businessValue,
                            scale = self._options.scale,
                            values = self._values,
                            sliderIndex = self.getIndex(),
                            anotherBusinessValue = self.getAnotherSlider().getValue(),
                            isValid = true,
                            minValue,
                            maxValue;
                        if (!scale.inverted && sliderIndex === START_VALUE_INDEX || scale.inverted && sliderIndex === END_VALUE_INDEX) {
                            if (scale.maxRange)
                                minValue = utils.addInterval(anotherBusinessValue, scale.maxRange, true);
                            if (scale.minRange)
                                maxValue = utils.addInterval(anotherBusinessValue, scale.minRange, true)
                        }
                        else {
                            if (scale.maxRange)
                                maxValue = utils.addInterval(anotherBusinessValue, scale.maxRange);
                            if (scale.minRange)
                                minValue = utils.addInterval(anotherBusinessValue, scale.minRange)
                        }
                        if (maxValue !== undefined && result > maxValue) {
                            result = values ? rangeSelector.utils.findLessOrEqualValue(values, maxValue) : maxValue;
                            isValid = false
                        }
                        else if (minValue !== undefined && result < minValue) {
                            result = values ? rangeSelector.utils.findGreaterOrEqualValue(values, minValue) : minValue;
                            isValid = false
                        }
                        self._setValid(isValid);
                        return result
                    },
                    _correctBusinessValueByMinRangeFromStartEndValues: function(businessValue) {
                        var self = this,
                            values = self._values,
                            startValue,
                            endValue,
                            isValid = true,
                            scale = self._options.scale,
                            result = businessValue;
                        if (scale.minRange)
                            if (self.getIndex() === END_VALUE_INDEX) {
                                startValue = utils.addInterval(scale.startValue, scale.minRange, scale.inverted);
                                if (!scale.inverted && result < startValue || scale.inverted && result > startValue)
                                    result = startValue
                            }
                            else if (self.getIndex() === START_VALUE_INDEX) {
                                endValue = utils.addInterval(scale.endValue, scale.minRange, !scale.inverted);
                                if (!scale.inverted && result > endValue || scale.inverted && result < endValue)
                                    result = endValue
                            }
                        return result
                    },
                    _applySliderPosition: function(position, disableAnimation) {
                        var self = this,
                            isAnimation = self._options.behavior.animationEnabled && !disableAnimation,
                            top = self._options.canvas.top,
                            slider = self._slider;
                        if (isAnimation || slider.inAnimation) {
                            slider.inAnimation = true;
                            slider.animate({translate: {
                                    x: position,
                                    y: top
                                }}, isAnimation ? animationOptions : {duration: 0}, function() {
                                slider.inAnimation = false
                            });
                            self._sliderTracker.animate({translate: {
                                    x: position,
                                    y: top
                                }}, isAnimation ? animationOptions : {duration: 0})
                        }
                        else {
                            self._slider.applySettings({
                                translateX: position,
                                translateY: top
                            });
                            self._sliderTracker.applySettings({
                                translateX: position,
                                translateY: top
                            })
                        }
                        self._sliderTracker.updateHeight();
                        self._slider.updateHeight()
                    },
                    _applyShutterPosition: function(position, disableAnimation) {
                        var self = this,
                            shutterSettings,
                            shutter = self._shutter,
                            isAnimation = self._options.behavior.animationEnabled && !disableAnimation,
                            sliderIndex = self.getIndex();
                        if (sliderIndex == START_VALUE_INDEX)
                            shutterSettings = {
                                x: self._options.canvas.left,
                                y: self._options.canvas.top,
                                width: position - self._options.canvas.left,
                                height: self._options.canvas.height
                            };
                        else if (sliderIndex == END_VALUE_INDEX)
                            shutterSettings = {
                                x: position + 1,
                                y: self._options.canvas.top,
                                width: self._options.canvas.left + self._options.canvas.width - position,
                                height: self._options.canvas.height
                            };
                        if (shutterSettings)
                            if (isAnimation || shutter.inAnimation) {
                                shutter.inAnimation = true;
                                shutter.animate(shutterSettings, isAnimation ? animationOptions : {duration: 0}, function() {
                                    shutter.inAnimation = false
                                })
                            }
                            else
                                shutter.applySettings(shutterSettings)
                    },
                    _setValid: function(isValid) {
                        var self = this;
                        if (self._marker)
                            self._marker.setValid(isValid);
                        self._slider.setValid(isValid)
                    },
                    _setText: function(text) {
                        var self = this;
                        if (self._marker)
                            self._marker.setText(text)
                    },
                    ctor: function(renderer, index) {
                        var self = this;
                        self.callBase(renderer);
                        self._index = index
                    },
                    getIndex: function() {
                        return this._index
                    },
                    setAvailableValues: function(values) {
                        this._values = values
                    },
                    setAnotherSlider: function(slider) {
                        this._anotherSlider = slider
                    },
                    getAnotherSlider: function(slider) {
                        return this._anotherSlider
                    },
                    appendTrackers: function(group) {
                        var self = this;
                        if (self._sliderTracker)
                            self._sliderTracker.append(group)
                    },
                    getSliderTracker: function() {
                        return this._sliderTracker
                    },
                    changeLocation: function() {
                        var self = this;
                        if (self._marker)
                            self._marker.changeLocation();
                        self._index = this._index === START_VALUE_INDEX ? END_VALUE_INDEX : START_VALUE_INDEX;
                        self._lastPosition = null
                    },
                    setPosition: function(position, correctByMinMaxRange, selectedRangeInterval) {
                        var self = this,
                            slider;
                        if (selectedRangeInterval !== undefined) {
                            slider = self.getIndex() === START_VALUE_INDEX ? self : self.getAnotherSlider();
                            slider._setPositionForBothSliders(position, selectedRangeInterval)
                        }
                        else
                            self._setPosition(position, correctByMinMaxRange)
                    },
                    getPosition: function() {
                        return this._position
                    },
                    _applyOptions: function(options) {
                        this._lastPosition = null
                    },
                    setValue: function(value, correctByMinMaxRange) {
                        var self = this;
                        if (value === undefined) {
                            self._value = undefined;
                            self._valuePosition = self._position = self.getIndex() === START_VALUE_INDEX ? self._options.canvas.left : self._options.canvas.left + self._options.canvas.width;
                            self._setText(rangeSelector.consts.emptySliderMarkerText)
                        }
                        else {
                            self._value = self._correctBusinessValue(value, correctByMinMaxRange);
                            self._valuePosition = self._position = self._options.translator.translateX(self._value);
                            self._setText(rangeSelector.formatValue(self._value, self._options.sliderMarker))
                        }
                    },
                    getValue: function() {
                        return this._value
                    },
                    canSwap: function() {
                        var self = this,
                            scale = self._options.scale,
                            startValue,
                            endValue,
                            anotherSliderValue;
                        if (self._options.behavior.allowSlidersSwap) {
                            if (scale.minRange) {
                                anotherSliderValue = self.getAnotherSlider().getValue();
                                if (self.getIndex() === START_VALUE_INDEX) {
                                    endValue = utils.addInterval(scale.endValue, scale.minRange, !scale.inverted);
                                    if (!scale.inverted && anotherSliderValue > endValue || scale.inverted && anotherSliderValue < endValue)
                                        return false
                                }
                                else {
                                    startValue = utils.addInterval(scale.startValue, scale.minRange, scale.inverted);
                                    if (!scale.inverted && anotherSliderValue < startValue || scale.inverted && anotherSliderValue > startValue)
                                        return false
                                }
                            }
                            return true
                        }
                        return false
                    },
                    processDocking: function() {
                        var self = this;
                        self._position = self._valuePosition;
                        self.applyPosition(false);
                        self._setValid(true)
                    },
                    applyPosition: function(disableAnimation) {
                        var self = this,
                            position = self.getPosition();
                        if (self._lastPosition !== position) {
                            self._applySliderPosition(position, disableAnimation);
                            self._applyShutterPosition(position, disableAnimation);
                            self._lastPosition = position
                        }
                    },
                    on: function(event, handler) {
                        var self = this;
                        self._sliderTracker.on(event, handler);
                        if (self._marker)
                            self._marker.getTracker().on(event, handler)
                    },
                    _update: function() {
                        var self = this;
                        self._marker && self._marker.applyOptions(self._options.sliderMarker);
                        self._shutter && self._shutter.applySettings({
                            fill: self._options.shutter.color,
                            fillOpacity: self._options.shutter.opacity
                        });
                        self._slider && self._slider.applyOptions({
                            strokeWidth: self._options.sliderHandle.width,
                            stroke: self._options.sliderHandle.color,
                            strokeOpacity: self._options.sliderHandle.opacity
                        })
                    },
                    _draw: function(group) {
                        var self = this,
                            slider,
                            marker,
                            sliderAreaGroup,
                            shutter,
                            startPos,
                            startWidth,
                            index = self.getIndex();
                        sliderAreaGroup = self._renderer.createGroup({'class': 'sliderArea'});
                        sliderAreaGroup.append(group);
                        if (index === START_VALUE_INDEX)
                            shutter = self._renderer.createRect(self._options.canvas.left, self._options.canvas.top, 0, self._options.canvas.height, 0);
                        else if (index === END_VALUE_INDEX)
                            shutter = self._renderer.createRect(self._options.canvas.left, self._options.canvas.top, self._options.canvas.width, self._options.canvas.height, 0);
                        if (shutter) {
                            shutter.append(sliderAreaGroup);
                            slider = self._createSlider();
                            if (slider)
                                slider.append(sliderAreaGroup);
                            if (self._options.sliderMarker.visible) {
                                marker = self._createSliderMarker({
                                    renderer: self._renderer,
                                    isLeftPointer: index === END_VALUE_INDEX,
                                    sliderMarkerOptions: self._options.sliderMarker
                                });
                                marker.draw(slider)
                            }
                            self._shutter = shutter;
                            self._slider = slider;
                            self._marker = marker
                        }
                        self._drawSliderTracker(group)
                    }
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file sliderMarker.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector;
        rangeSelector.SliderMarker = DX.Class.inherit(function() {
            var ctor = function(options) {
                    this._renderer = options.renderer;
                    this._text = options.text;
                    this._isLeftPointer = options.isLeftPointer;
                    this._options = options.sliderMarkerOptions;
                    this._isValid = true;
                    initializeAreaPoints(this, {
                        width: 10,
                        height: 10
                    })
                };
            var applyOptions = function(options) {
                    this._options = options;
                    this.update()
                };
            var getRectSize = function(self, textSize) {
                    return {
                            width: Math.round(2 * self._options.padding + textSize.width),
                            height: Math.round(2 * self._options.padding + textSize.height * rangeSelector.consts.fontHeightRatio)
                        }
                };
            var initializeAreaPoints = function(self, textSize) {
                    var rectSize = getRectSize(self, textSize);
                    self._points = [];
                    if (self._isLeftPointer) {
                        self._points.push({
                            x: 0,
                            y: 0
                        });
                        self._points.push({
                            x: rectSize.width,
                            y: 0
                        });
                        self._points.push({
                            x: rectSize.width,
                            y: rectSize.height
                        });
                        self._points.push({
                            x: self._options.pointerSize,
                            y: rectSize.height
                        });
                        self._points.push({
                            x: 0,
                            y: rectSize.height + self._options.pointerSize
                        })
                    }
                    else {
                        self._points.push({
                            x: 0,
                            y: 0
                        });
                        self._points.push({
                            x: rectSize.width,
                            y: 0
                        });
                        self._points.push({
                            x: rectSize.width,
                            y: rectSize.height + self._options.pointerSize
                        });
                        self._points.push({
                            x: rectSize.width - self._options.pointerSize,
                            y: rectSize.height
                        });
                        self._points.push({
                            x: 0,
                            y: rectSize.height
                        })
                    }
                };
            var getPointerPosition = function(self, textSize) {
                    var rectSize = getRectSize(self, textSize);
                    if (self._isLeftPointer)
                        return {
                                x: 0,
                                y: rectSize.height + self._options.pointerSize
                            };
                    else
                        return {
                                x: rectSize.width - 1,
                                y: rectSize.height + self._options.pointerSize
                            }
                };
            var draw = function(group) {
                    var self = this;
                    var padding = self._options.padding;
                    self._sliderMarkerGroup = self._renderer.createGroup({'class': 'sliderMarker'});
                    self._sliderMarkerGroup.append(group);
                    self._area = self._renderer.createArea(self.points, {fill: self._options.color});
                    self._area.append(self._sliderMarkerGroup);
                    self._label = self._renderer.createText(self._text, padding, padding, {
                        font: self._options.font,
                        style: {'-webkit-user-select': 'none'}
                    });
                    self._label.append(self._sliderMarkerGroup);
                    self._tracker = self._renderer.createRect(0, 0, 2 * padding, 2 * padding + self._options.pointerSize, 0, {
                        fill: 'grey',
                        stroke: 'grey',
                        opacity: 0.0001,
                        style: {cursor: 'pointer'}
                    });
                    self._tracker.append(self._sliderMarkerGroup);
                    self._drawn = true;
                    self.update()
                };
            var getTextSize = function(self) {
                    var textSize = self._label.getBBox();
                    if (!self._textHeight && isFinite(textSize.height))
                        self._textHeight = textSize.height;
                    return {
                            width: textSize.width,
                            height: self._textHeight
                        }
                };
            var update = function(stop) {
                    var self = this,
                        textSize,
                        rectSize,
                        pointerPosition;
                    self._interval && clearInterval(self._interval);
                    delete self._interval;
                    if (!self._drawn)
                        return;
                    self._label.updateText(self._text);
                    textSize = getTextSize(self);
                    if (!stop) {
                        self._textSize = self._textSize || textSize;
                        self._textSize = textSize.width > self._textSize.width || textSize.height > self._textSize.height ? textSize : self._textSize;
                        textSize = self._textSize;
                        self._interval = setInterval(function() {
                            update.call(self, [true])
                        }, 75)
                    }
                    else {
                        delete self._textSize;
                        self._textSize = textSize
                    }
                    rectSize = getRectSize(self, textSize);
                    pointerPosition = getPointerPosition(self, textSize);
                    self._sliderMarkerGroup.applySettings({
                        translateX: -pointerPosition.x,
                        translateY: -pointerPosition.y
                    });
                    initializeAreaPoints(self, textSize);
                    self._area.applySettings({
                        points: self._points,
                        fill: self._isValid ? self._options.color : self._options.invalidRangeColor
                    });
                    self._tracker.applySettings({
                        width: rectSize.width,
                        height: rectSize.height + self._options.pointerSize
                    });
                    self._label.applySettings({
                        x: self._options.padding,
                        y: rectSize.height - self._options.padding
                    })
                };
            var getText = function() {
                    var self = this;
                    return self._text
                };
            var setText = function(value) {
                    var self = this;
                    if (self._text !== value) {
                        self._text = value;
                        self.update()
                    }
                };
            var setValid = function(isValid) {
                    var self = this;
                    self._isValid = isValid;
                    self.update()
                };
            var changeLocation = function() {
                    var self = this;
                    self._isLeftPointer = !self._isLeftPointer;
                    self.update()
                };
            var getTracker = function() {
                    var self = this;
                    return self._tracker
                };
            return {
                    ctor: ctor,
                    draw: draw,
                    update: update,
                    getText: getText,
                    setText: setText,
                    changeLocation: changeLocation,
                    applyOptions: applyOptions,
                    getTracker: getTracker,
                    setValid: setValid
                }
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file rangeView.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector;
        rangeSelector.RangeView = rangeSelector.BaseVisualElement.inherit(function() {
            var createThemeManager = function(self) {
                    return DX.viz.charts.factory.createThemeManager(self.chart.theme)
                };
            return {_draw: function(group) {
                        var self = this,
                            viewRect,
                            viewImage,
                            backgroundColor,
                            series,
                            i,
                            showChart,
                            canvas,
                            isEmpty = self._options.isEmpty;
                        showChart = self._options.seriesDataSource && self._options.seriesDataSource.isShowChart() && !isEmpty;
                        canvas = self._options.canvas;
                        if (showChart)
                            backgroundColor = self._options.seriesDataSource.getBackgroundColor();
                        else if (!isEmpty && self._options.background.visible)
                            backgroundColor = self._options.background.color;
                        if (self._options.background.visible && backgroundColor) {
                            viewRect = self._renderer.createRect(canvas.left, canvas.top, canvas.width + 1, canvas.height, 0, {
                                fill: backgroundColor,
                                'class': 'dx-range-selector-background'
                            });
                            viewRect.append(group)
                        }
                        if (self._options.background.visible && self._options.background.image && self._options.background.image.url) {
                            viewImage = self._renderer.createImage(canvas.left, canvas.top, canvas.width + 1, canvas.height, self._options.background.image.url, {location: self._options.background.image.location});
                            viewImage.append(group)
                        }
                        if (showChart) {
                            series = self._options.seriesDataSource.getSeries();
                            for (i = 0; i < series.length; i++) {
                                series[i].options.seriesGroup = group;
                                series[i].options.seriesLabelsGroup = group;
                                series[i].options.trackerGroup = group;
                                if (self._options.chart.useAggregation)
                                    series[i].resamplePoints(self._options.translator);
                                series[i].draw(self._options.translator, self._options.behavior && self._options.behavior.animationEnabled && self._renderer.animationEnabled())
                            }
                        }
                    }}
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file seriesDataSource.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            charts = DX.viz.charts;
        rangeSelector.SeriesDataSource = DX.Class.inherit(function() {
            var createThemeManager = function(chartOptions) {
                    return charts.factory.createThemeManager(chartOptions, 'rangeSelector.chart')
                };
            var isArrayOfSimpleTypes = function(data) {
                    return $.isArray(data) && data.length > 0 && (DX.utils.isNumber(data[0]) || DX.utils.isDate(data[0]))
                };
            var convertToArrayOfObjects = function(data) {
                    return $.map(data, function(item, i) {
                            return {
                                    arg: item,
                                    val: i
                                }
                        })
                };
            var calculateSeries = function(self, options) {
                    var series = [],
                        particularSeriesOptions,
                        seriesTheme,
                        data,
                        parsedData,
                        temp,
                        chartThemeManager = createThemeManager(options.chart),
                        allSeriesOptions = options.chart.series,
                        seriesValueType = options.chart.valueAxis && options.chart.valueAxis.valueType,
                        dataSourceField,
                        chartOptions,
                        i;
                    if (options.dataSource && !allSeriesOptions) {
                        if (isArrayOfSimpleTypes(options.dataSource))
                            options.dataSource = convertToArrayOfObjects(options.dataSource);
                        dataSourceField = options.dataSourceField || 'arg';
                        allSeriesOptions = {
                            argumentField: dataSourceField,
                            valueField: dataSourceField
                        };
                        self._hideChart = true
                    }
                    allSeriesOptions = $.isArray(allSeriesOptions) ? allSeriesOptions : allSeriesOptions ? [allSeriesOptions] : [];
                    chartOptions = chartThemeManager.applyTheme(chartThemeManager.getTheme(), options.chart);
                    $.extend(chartOptions.commonSeriesSettings, {
                        argumentType: options.valueType,
                        valueType: dataSourceField ? options.valueType : seriesValueType,
                        incidentOccured: options.incidentOccured
                    });
                    self._backgroundColor = options.backgroundColor !== undefined ? options.backgroundColor : chartOptions.backgroundColor;
                    for (i = 0; i < allSeriesOptions.length; i++) {
                        particularSeriesOptions = allSeriesOptions[i];
                        particularSeriesOptions.rotated = false;
                        data = options.dataSource;
                        seriesTheme = chartThemeManager.applyNextSeriesTheme(particularSeriesOptions, chartOptions.commonSeriesSettings);
                        if (data && data.length > 0) {
                            var newSeries = charts.factory.createSeries(particularSeriesOptions.type || chartOptions.commonSeriesSettings.type, options.renderer, seriesTheme);
                            newSeries._suppressTrackers = true;
                            series.push(newSeries)
                        }
                    }
                    self._dataValidator = charts.factory.createDataValidator(data, [series], options.incidentOccured, chartOptions.dataPrepareSettings);
                    parsedData = self._dataValidator.validate();
                    for (i = 0; i < series.length; i++) {
                        var particularSeries = series[i];
                        particularSeries.reinitData(parsedData)
                    }
                    return series
                };
            var processSeriesFamilies = function(series, equalBarWidth) {
                    var families = [],
                        types = [];
                    $.each(series, function(i, item) {
                        if ($.inArray(item.type, types) === -1)
                            types.push(item.type)
                    });
                    $.each(types, function(_, type) {
                        var family = new charts.factory.createSeriesFamily({
                                type: type,
                                equalBarWidth: equalBarWidth
                            });
                        family.add(series);
                        family.adjustSeriesValues();
                        families.push(family)
                    });
                    return families
                };
            var prototypeObject = {
                    ctor: function(options) {
                        var self = this;
                        self._indent = {
                            top: options.chart.topIndent >= 0 && options.chart.topIndent < 1 ? options.chart.topIndent : 0,
                            bottom: options.chart.bottomIndent >= 0 && options.chart.bottomIndent < 1 ? options.chart.bottomIndent : 0
                        };
                        self._valueAxis = options.chart.valueAxis || {};
                        self._hideChart = false;
                        self._series = calculateSeries(self, options);
                        self._seriesFamilies = processSeriesFamilies(self._series, options.chart.equalBarWidth)
                    },
                    adjustSeriesDimensions: function(translator) {
                        var self = this;
                        $.each(self._seriesFamilies, function() {
                            this.adjustSeriesDimensions(translator)
                        })
                    },
                    getBoundRange: function() {
                        var self = this,
                            seriesElement,
                            rangeData,
                            range = new charts.Range({
                                minY: self._valueAxis.min,
                                minVisibleY: self._valueAxis.min,
                                maxY: self._valueAxis.max,
                                maxVisibleY: self._valueAxis.max
                            }),
                            rangeYSize,
                            rangeVisibleSizeY,
                            i,
                            minIndent,
                            maxIndent;
                        for (i = 0; i < self._series.length; i++) {
                            rangeData = self._series[i].getRangeData();
                            range = range.getBoundRange(rangeData)
                        }
                        if (range.isDefined()) {
                            minIndent = self._valueAxis.inverted ? self._indent.top : self._indent.bottom;
                            maxIndent = self._valueAxis.inverted ? self._indent.bottom : self._indent.top;
                            rangeYSize = range.maxY - range.minY;
                            rangeVisibleSizeY = ($.isNumeric(range.maxVisibleY) ? range.maxVisibleY : range.maxY) - ($.isNumeric(range.minVisibleY) ? range.minVisibleY : range.minY);
                            range.minY -= rangeYSize * minIndent;
                            range.maxY += rangeYSize * maxIndent;
                            if ($.isNumeric(rangeVisibleSizeY)) {
                                range.maxVisibleY = range.maxVisibleY ? range.maxVisibleY + rangeVisibleSizeY * maxIndent : undefined;
                                range.minVisibleY = range.minVisibleY ? range.minVisibleY - rangeVisibleSizeY * minIndent : undefined
                            }
                            range.invertY = self._valueAxis.inverted
                        }
                        return range
                    },
                    getSeries: function() {
                        var self = this;
                        return self._series
                    },
                    getBackgroundColor: function() {
                        var self = this;
                        return self._backgroundColor
                    },
                    isEmpty: function() {
                        var self = this;
                        return self.getSeries().length === 0
                    },
                    isShowChart: function() {
                        var self = this;
                        return !self.isEmpty() && !self._hideChart
                    },
                    getCalculatedValueType: function() {
                        var self = this,
                            result;
                        if (self._series.length)
                            result = self._series[0].options.argumentType;
                        return result
                    }
                };
            return prototypeObject
        }())
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file utils.js */
    (function($, DX, undefined) {
        var rangeSelector = DX.viz.rangeSelector,
            utils = rangeSelector.utils,
            dxUtils = DX.utils;
        var INVISIBLE_POS = -1000;
        var findLessOrEqualValueIndex = function(values, value) {
                if (!values || values.length === 0)
                    return -1;
                var minIndex = 0,
                    maxIndex = values.length - 1,
                    index = 0;
                while (maxIndex - minIndex > 1) {
                    var index = minIndex + maxIndex >> 1;
                    if (values[index] > value)
                        maxIndex = index;
                    else
                        minIndex = index
                }
                return values[maxIndex] <= value ? maxIndex : minIndex
            };
        var findLessOrEqualValue = function(values, value) {
                var index = findLessOrEqualValueIndex(values, value);
                if (values && index >= 0 && index < values.length)
                    return values[index];
                return value
            };
        var findNearValue = function(values, value) {
                var index = findLessOrEqualValueIndex(values, value);
                if (values && index >= 0 && index < values.length) {
                    if (index + 1 < values.length)
                        if (dxUtils.isDate(value)) {
                            if (values[index + 1].getTime() - value.getTime() < value.getTime() - values[index].getTime())
                                index++
                        }
                        else if (values[index + 1] - value < value - values[index])
                            index++;
                    return values[index]
                }
                return value
            };
        var findGreaterOrEqualValue = function(values, value) {
                var index = findLessOrEqualValueIndex(values, value);
                if (values && index >= 0 && index < values.length) {
                    if (values[index] < value && index + 1 < values.length)
                        index++;
                    return values[index]
                }
                return value
            };
        var getInterval = function(valueMin, valueMax, delta) {
                var result,
                    minDateDaysCount,
                    maxDateDaysCount,
                    daysCount,
                    prevMaxDaysCount;
                if (dxUtils.isDate(valueMin)) {
                    if (delta === 'year' || delta === 'quarter' || delta === 'month')
                        return {months: valueMax.getFullYear() * 12 + valueMax.getMonth() - valueMin.getFullYear() * 12 - valueMin.getMonth()};
                    else
                        return {milliseconds: valueMax.valueOf() - valueMin.valueOf()};
                    return result
                }
                else
                    return valueMax - valueMin
            };
        var getRootOffsetLeft = function(renderer) {
                return dxUtils.getRootOffset(renderer).left || 0
            };
        var getEventPageX = function(eventArgs) {
                var result = 0;
                if (eventArgs.pageX)
                    result = eventArgs.pageX;
                else if (eventArgs.originalEvent && eventArgs.originalEvent.pageX)
                    result = eventArgs.originalEvent.pageX;
                if (eventArgs.originalEvent && eventArgs.originalEvent.touches)
                    if (eventArgs.originalEvent.touches.length > 0)
                        result = eventArgs.originalEvent.touches[0].pageX;
                    else if (eventArgs.originalEvent.changedTouches.length > 0)
                        result = eventArgs.originalEvent.changedTouches[0].pageX;
                return result
            };
        var getTextBBox = function(renderer, text, fontOptions) {
                var textElement = renderer.createText(text, INVISIBLE_POS, INVISIBLE_POS, {font: fontOptions}).append();
                var textBBox = textElement.getBBox();
                textElement.remove();
                return textBBox
            };
        utils.findLessOrEqualValue = findLessOrEqualValue;
        utils.findNearValue = findNearValue;
        utils.findGreaterOrEqualValue = findGreaterOrEqualValue;
        utils.getInterval = getInterval;
        utils.getRootOffsetLeft = getRootOffsetLeft;
        utils.getEventPageX = getEventPageX;
        utils.getTextBBox = getTextBBox
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file themeManager.js */
    (function($, DX, undefined) {
        DX.viz.rangeSelector = DX.viz.rangeSelector;
        DX.viz.rangeSelector.ThemeManager = DX.viz.core.BaseThemeManager.inherit({
            ctor: function(userTheme) {
                var self = this;
                self.callBase(userTheme, 'rangeSelector');
                self.initializeFont(self.theme.scale.label.font);
                self.initializeFont(self.theme.sliderMarker.font)
            },
            applyRangeSelectorTheme: function(userOptions) {
                var self = this,
                    refs = {dataSource: userOptions.dataSource},
                    result;
                delete userOptions.dataSource;
                result = self.applyTheme(self.theme, userOptions);
                result.dataSource = refs.dataSource;
                return result
            },
            setBackgroundColor: function(containerBackgroundColor) {
                var theme = this.theme;
                if (containerBackgroundColor)
                    theme.containerBackgroundColor = containerBackgroundColor;
                theme.shutter.color = theme.shutter.color || theme.containerBackgroundColor
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-rangeselector, file dxRangeSelector.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        ui.registerComponent("dxRangeSelector", viz.rangeSelector.RangeSelector)
    })(jQuery, DevExpress);
    DevExpress.MOD_VIZ_RANGESELECTOR = true
}
if (!DevExpress.MOD_VIZ_VECTORMAP) {
    if (!window.DevExpress)
        throw Error('Required module is not referenced: core');
    if (!DevExpress.MOD_VIZ_CORE)
        throw Error('Required module is not referenced: viz-core');
    /*! Module viz-vectormap, file map.js */
    (function(DX, $, undefined) {
        DX.viz.map = {};
        DX.viz.map._tests = {};
        var _Number = window.Number,
            _String = window.String,
            _isFinite = window.isFinite,
            _setTimeout = window.setTimeout,
            _clearTimeout = window.clearTimeout,
            _round = Math.round,
            _abs = Math.abs,
            _max = Math.max,
            _min = Math.min,
            _pow = Math.pow,
            _ln = Math.log,
            _exp = Math.exp,
            _tan = Math.tan,
            _atan = Math.atan,
            _isArray = DX.utils.isArray,
            _isFunction = DX.utils.isFunction,
            _isString = DX.utils.isString,
            _windowResizeCallbacks = DX.utils.windowResizeCallbacks,
            _createResizeHandler = DX.utils.createResizeHandler,
            _getRootOffset = DX.utils.getRootOffset,
            _buildPath = DX.viz.renderers.buildPath,
            _Color = DX.Color,
            _ajax = $.ajax,
            _extend = $.extend;
        var _LN2 = Math.LN2;
        var COMMAND_RESET = 'command-reset',
            COMMAND_MOVE_UP = 'command-move-up',
            COMMAND_MOVE_RIGHT = 'command-move-right',
            COMMAND_MOVE_DOWN = 'command-move-down',
            COMMAND_MOVE_LEFT = 'command-move-left',
            COMMAND_ZOOM_IN = 'command-zoom-in',
            COMMAND_ZOOM_OUT = 'command-zoom-out',
            COMMAND_ZOOM_DRAG = 'command-zoom-drag';
        var DEFAULT_WIDTH = 800,
            DEFAULT_HEIGHT = 400;
        var MIN_ZOOM = 1,
            MAX_ZOOM = 32;
        var TOOLTIP_SHOW_DELAY = 300,
            TOOLTIP_HIDE_DELAY = 300,
            TOOLTIP_TOUCH_SHOW_DELAY = 400,
            TOOLTIP_TOUCH_HIDE_DELAY = 300;
        var SELECTION_MODE_NONE = 'none',
            SELECTION_MODE_SINGLE = 'single',
            SELECTION_MODE_MULTIPLE = 'multiple';
        var FLAG_NO_CALLBACK = 1,
            FLAG_NO_CHECK = 2;
        DX.viz.map.Map = DX.ui.Component.inherit({
            _rendererType: DX.viz.renderers.Renderer,
            _init: function() {
                var self = this;
                self.callBase();
                self._renderer = new self._rendererType;
                self._renderer.recreateCanvas(1, 1);
                self._renderer.draw(self._element().get(0));
                self._themeManager = new self._themeManagerType;
                self._projection = new self._projectionType;
                self._tracker = new self._trackerType;
                self._root = self._renderer.getRoot();
                self._root.applySettings({
                    'class': 'dxm',
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: 'none',
                    align: 'center',
                    cursor: 'default',
                    style: {overflow: 'hidden'}
                });
                self._background = self._renderer.createSimplePath({'class': 'dxm-background'});
                self._tracker.attachRoot(self._root);
                self._tracker.setCallbacks(self, {
                    start: startCallback,
                    move: moveCallback,
                    end: endCallback,
                    wheel: wheelCallback,
                    'hover-on': hoverOnCallback,
                    'hover-off': hoverOffCallback,
                    click: clickCallback,
                    'tooltip-check': checkTooltipCallback,
                    'tooltip-show': showTooltipCallback,
                    'tooltip-move': moveTooltipCallback,
                    'tooltip-hide': hideTooltipCallback
                });
                self._initAreas();
                self._initMarkers();
                self._controlBar = new self._controlBarType({
                    container: self._root,
                    renderer: self._renderer,
                    context: self,
                    resetCallback: controlResetCallback,
                    moveCallback: controlMoveCallback,
                    zoomCallback: controlZoomCallback
                });
                self._tooltip = new self._tooltipType({
                    container: self._root,
                    renderer: self._renderer
                });
                self._legend = new self._legendType({
                    container: self._root,
                    renderer: self._renderer,
                    themeManager: self._themeManager
                });
                self._initResizing();
                self._debug_renderer = self._renderer;
                self._debug_themeManager = self._themeManager;
                self._debug_projection = self._projection;
                self._debug_tracker = self._tracker;
                self._debug_controlBar = self._controlBar;
                self._debug_tooltip = self._tooltip;
                self._debug_legend = self._legend
            },
            _initAreas: function() {
                var self = this;
                self._areasGroup = self._renderer.createGroup({'class': 'dxm-areas'});
                self._areasCancelLock = 0;
                self._tracker.attachGroup('areas', self._areasGroup)
            },
            _initMarkers: function() {
                var self = this,
                    options = _extend({}, self.option('marker'));
                self._markersGroup = self._renderer.createGroup({'class': 'dxm-markers'});
                self._markerShapesGroup = self._renderer.createGroup();
                self._markerTextsGroup = self._renderer.createGroup({'class': 'dxm-marker-texts'});
                self._markerCoversGroup = self._renderer.createGroup({
                    stroke: 'none',
                    strokeWidth: 0,
                    fill: '#000000',
                    opacity: 0.0001
                });
                self._markerShadowFilter = self._renderer.createFilter('shadow').applySettings({
                    id: 'shadow-filter',
                    x: '-40%',
                    y: '-40%',
                    width: '180%',
                    height: '200%',
                    color: '#000000',
                    opacity: 0.2,
                    dx: 0,
                    dy: 1,
                    blur: 1
                }).append();
                self._markersCancelLock = 0;
                self._tracker.attachGroup('markers', self._markersGroup)
            },
            _initResizing: function() {
                var self = this;
                self._resizeHandler = _createResizeHandler(function() {
                    self._resize()
                });
                self._resizeHandler.dispose = function() {
                    self = null;
                    return this
                };
                _windowResizeCallbacks.add(self._resizeHandler)
            },
            _dispose: function() {
                var self = this;
                self.callBase();
                delete self._root;
                delete self._background;
                self._themeManager.dispose() && delete self._themeManager;
                self._tracker.detachRoot();
                self._disposeAreas();
                self._disposeMarkers();
                self._controlBar.dispose() && delete self._controlBar;
                self._tooltip.dispose() && delete self._tooltip;
                self._legend.dispose() && delete self._legend;
                self._renderer.dispose();
                delete self._renderer;
                delete self._projection;
                self._tracker.dispose() && delete self._tracker;
                delete self._readyCallback;
                self._disposeResizing();
                self._remoteDataCache = null;
                delete self._debug_renderer;
                delete self._debug_themeManager;
                delete self._debug_projection;
                delete self._debug_tracker;
                delete self._debug_controlBar;
                delete self._debug_tooltip;
                delete self._debug_legend
            },
            _disposeAreas: function() {
                var self = this;
                self._areasGroup = self._areasInfo = self._areasDataItems = null;
                self._tracker.detachGroup('areas')
            },
            _disposeMarkers: function() {
                var self = this;
                self._markersGroup.clear();
                self._markerShadowFilter.dispose();
                self._markersGroup = self._markerShapesGroup = self._markerTextsGroup = self._markerCoversGroup = self._markerShadowFilter = self._markersDataItems = null;
                self._tracker.detachGroup('markers')
            },
            _disposeResizing: function() {
                var self = this;
                _windowResizeCallbacks.remove(self._resizeHandler);
                self._resizeHandler.stop().dispose() && delete self._resizeHandler
            },
            _adjustSize: function() {
                var self = this,
                    size = self.option('size') || {},
                    width = size.width >= 0 ? _Number(size.width) : self._element().width(),
                    height = size.height >= 0 ? _Number(size.height) : self._element().height();
                width === 0 && _Number(size.width) !== 0 && (width = DEFAULT_WIDTH);
                height === 0 && _Number(size.height) !== 0 && (height = DEFAULT_HEIGHT);
                var needResize = self._width !== width || self._height !== height;
                if (needResize) {
                    self._renderer.resize(width, height);
                    self._projection.setSize(width, height);
                    self._applyTransform();
                    self._tooltip.setSize(width, height);
                    self._legend.setSize(width, height);
                    self._background.applySettings({d: _buildPath([0, 0, width, 0, width, height, 0, height])});
                    self._width = width;
                    self._height = height
                }
                return needResize
            },
            _clean: function() {
                var self = this;
                self._themeManager.reset();
                self._background.detach();
                self._cleanAreas();
                self._cleanMarkers();
                self._controlBar.clean();
                self._legend.clean();
                self._tooltip.clean();
                self._tracker.clean()
            },
            _render: function() {
                var self = this;
                self._projection.setBounds(self.option('bounds')).setZoom(self.option('zoomFactor')).setCenter(self.option('center'));
                self._adjustSize();
                self._themeManager.setTheme(self.option('theme'));
                self._tooltip.setOptions(self._themeManager.getTooltipSettings(self.option('tooltip')));
                self._legend.setOptions(self._themeManager.getLegendSettings(self.option('legend')));
                self._tracker.setOptions(self._getTrackerSettings());
                self._controlBar.setZoom(self._projection.getZoom()).setOptions(self._themeManager.getControlBarSettings(self.option('controlBar')));
                _isFunction(self._readyCallback = self.option('ready')) || (self._readyCallback = null);
                self._applyTransform();
                self._background.applySettings(self._themeManager.getBackgroundSettings(self.option('background')));
                self._background.append(self._root);
                self._renderAreas();
                self._renderMarkers();
                self._controlBar.render();
                self._legend.render();
                self._tooltip.render();
                self._tracker.render();
                self._contentReady = true;
                self._raiseReady()
            },
            _getTrackerSettings: function() {
                var interaction = this.option('interaction'),
                    settings = {};
                if (interaction !== undefined && !interaction)
                    settings.enabled = false;
                else {
                    interaction = interaction || {};
                    settings.enabled = true;
                    settings.touchEnabled = interaction.touchEnabled !== undefined ? !!interaction.touchEnabled : true;
                    settings.wheelEnabled = interaction.wheelEnabled !== undefined ? !!interaction.wheelEnabled : true;
                    settings.tooltipEnabled = this._tooltip.enabled()
                }
                return settings
            },
            _optionChanged: function(name, value) {
                switch (name) {
                    case'zoomFactor':
                        this._updateZoomFactor(value);
                        break;
                    case'center':
                        this._updateCenter(value);
                        break;
                    default:
                        this._invalidate();
                        break
                }
            },
            _updateZoomFactor: function(zoomFactor) {
                var self = this,
                    zoom = self._projection.getZoom();
                self._projection.setZoom(zoomFactor);
                if (zoom !== self._projection.getZoom()) {
                    self._controlBar.setZoom(self._projection.getZoom());
                    self._applyTransform(true)
                }
            },
            _updateCenter: function(center) {
                var self = this;
                self._projection.setCenter(center);
                self._applyTransform()
            },
            _resize: function() {
                var self = this;
                if (self._adjustSize()) {
                    self._applyTransform();
                    self._parseAreas();
                    self._redrawAreas();
                    self._parseMarkers();
                    self._redrawMarkers();
                    self._debug_resized && self._debug_resized()
                }
            },
            _raiseReady: function() {
                var self = this;
                if (self._areasReady && self._markersReady && self._contentReady) {
                    self._areasReady = self._markersReady = self._contentReady = null;
                    self._readyCallback && self._readyCallback();
                    self._debug_ready && self._debug_ready()
                }
            },
            _loadData: function(dataSource, callback) {
                if (_isArray(dataSource))
                    callback(dataSource);
                else if (_isString(dataSource)) {
                    var cache = this._remoteDataCache = this._remoteDataCache || {};
                    if (cache[dataSource])
                        callback(cache[dataSource]);
                    else
                        _ajax({
                            url: dataSource,
                            dataType: 'json',
                            type: 'GET',
                            success: function(data, status, xhr) {
                                cache[dataSource] = _isArray(data) ? data : [];
                                callback(cache[dataSource])
                            },
                            error: function(xhr, status, error) {
                                callback([], error)
                            }
                        })
                }
                else
                    callback([])
            },
            _cleanAreas: function() {
                var self = this;
                self._areaCustomizeCallback = self._areaClickCallback = self._areaSelectionChangedCallback = self._selectedAreas = null;
                self._areasGroup.detach();
                self._areasGroup.clear();
                var areasInfo = self._areasInfo;
                if (areasInfo) {
                    var i = 0,
                        ii = areasInfo.length;
                    for (; i < ii; ++i)
                        areasInfo[i].proxy._dispose();
                    self._areasInfo = null
                }
                else
                    ++self._areasCancelLock
            },
            _renderAreas: function() {
                var self = this,
                    options = self.option('areaSettings') || {},
                    dataSource = self.option('mapData');
                self._themeManager.initCommonAreaSettings(options);
                self._areaCustomizeCallback = _isFunction(options.customize) ? options.customize : null;
                self._areaClickCallback = _isFunction(options.click) ? options.click : null;
                self._areaSelectionChangedCallback = _isFunction(options.selectionChanged) ? options.selectionChanged : null;
                self._areaHoverEnabled = 'hoverEnabled' in options ? !!options.hoverEnabled : true;
                var selectionMode = _String(options.selectionMode).toLowerCase();
                self._areaSelectionMode = selectionMode === SELECTION_MODE_NONE || selectionMode === SELECTION_MODE_SINGLE || selectionMode === SELECTION_MODE_MULTIPLE ? selectionMode : SELECTION_MODE_SINGLE;
                self._selectedAreas = self._areaSelectionMode === SELECTION_MODE_MULTIPLE ? {} : null;
                self._areasGroup.append(self._root);
                self._loadData(dataSource, function(dataItems) {
                    self._areasDataItems = dataItems;
                    self._areasCancelLock === 0 ? self._createAreas() : --self._areasCancelLock;
                    self = null
                })
            },
            _parseAreas: function() {
                var areasInfo = this._areasInfo,
                    dataItems = this._areasDataItems,
                    projection = this._projection,
                    i = 0,
                    ii = dataItems.length;
                for (; i < ii; ++i)
                    (areasInfo[i] = areasInfo[i] || {}).coordinates = projection.parseAreaData(dataItems[i].coordinates)
            },
            _createAreas: function() {
                var self = this,
                    areasInfo = self._areasInfo = [];
                self._parseAreas();
                var group = self._areasGroup,
                    renderer = self._renderer,
                    themeManager = self._themeManager,
                    projection = self._projection,
                    dataItems = self._areasDataItems,
                    customizeCallback = self._areaCustomizeCallback,
                    areaInfo,
                    dataItem,
                    i = 0,
                    ii = areasInfo.length,
                    selectedList = [],
                    element,
                    path;
                group.applySettings(themeManager.getCommonAreaSettings().common);
                for (; i < ii; ++i) {
                    areaInfo = areasInfo[i];
                    dataItem = dataItems[i];
                    element = null;
                    areaInfo.attributes = dataItem.attributes = dataItem.attributes || {};
                    areaInfo.options = (customizeCallback ? customizeCallback.call(dataItem, dataItem) : null) || {};
                    path = projection.projectArea(areaInfo.coordinates);
                    areaInfo.styles = themeManager.getAreaSettings(areaInfo.options);
                    areaInfo.element = element = renderer.createSimplePath({d: path});
                    element.applySettings(areaInfo.styles.normal);
                    areaInfo.index = i;
                    setElementData(element.$element, i);
                    areaInfo.options.isSelected && selectedList.push(areaInfo);
                    areaInfo.proxy = new ElementProxy(self, areaInfo, {
                        type: 'area',
                        setSelectionCallback: self._setAreaSelection
                    });
                    element.append(group)
                }
                ii = self._areaSelectionMode !== SELECTION_MODE_NONE ? selectedList.length : 0;
                i = ii > 0 && self._areaSelectionMode === SELECTION_MODE_SINGLE ? ii - 1 : 0;
                for (; i < ii; ++i)
                    self._setAreaSelection(selectedList[i], true, FLAG_NO_CALLBACK);
                self._areasReady = true;
                self._raiseReady()
            },
            _redrawAreas: function() {
                var areasInfo = this._areasInfo,
                    projection = this._projection,
                    areaInfo,
                    i = 0,
                    ii = areasInfo.length;
                for (; i < ii; ++i) {
                    areaInfo = areasInfo[i];
                    areaInfo.element.applySettings({d: projection.projectArea(areaInfo.coordinates)})
                }
                this._DEBUG_areasRedrawn && this._DEBUG_areasRedrawn()
            },
            _cleanMarkers: function() {
                var self = this;
                self._markerCustomizeCallback = self._markerClickCallback = self._markerSelectionChangedCallback = self._selectedMarkers = null;
                self._markersGroup.detach();
                self._markerShapesGroup.detach();
                self._markerTextsGroup.detach();
                self._markerCoversGroup.detach();
                self._markerShapesGroup.clear();
                self._markerTextsGroup.clear();
                self._markerCoversGroup.clear();
                var markersInfo = self._markersInfo;
                if (markersInfo) {
                    var i = 0,
                        ii = markersInfo.length;
                    for (; i < ii; ++i)
                        markersInfo[i].proxy._dispose();
                    self._markersInfo = null
                }
                else
                    ++self._markersCancelLock
            },
            _renderMarkers: function() {
                var self = this,
                    options = self.option('markerSettings') || {},
                    dataSource = self.option('markers');
                self._themeManager.initCommonMarkerSettings(options);
                self._markerCustomizeCallback = _isFunction(options.customize) ? options.customize : null;
                self._markerClickCallback = _isFunction(options.click) ? options.click : null;
                self._markerSelectionChangedCallback = _isFunction(options.selectionChanged) ? options.selectionChanged : null;
                self._markerHoverEnabled = 'hoverEnabled' in options ? !!options.hoverEnabled : true;
                var selectionMode = _String(options.selectionMode).toLowerCase();
                self._markerSelectionMode = selectionMode === SELECTION_MODE_NONE || selectionMode === SELECTION_MODE_SINGLE || selectionMode === SELECTION_MODE_MULTIPLE ? selectionMode : SELECTION_MODE_SINGLE;
                self._selectedMarkers = self._markerSelectionMode === SELECTION_MODE_MULTIPLE ? {} : null;
                self._markersGroup.append(self._root);
                self._loadData(dataSource, function(dataItems) {
                    self._markersDataItems = dataItems;
                    self._markersCancelLock === 0 ? self._createMarkers() : --self._markersCancelLock;
                    self = null
                })
            },
            _parseMarkers: function() {
                var markersInfo = this._markersInfo,
                    dataItems = this._markersDataItems,
                    projection = this._projection,
                    i = 0,
                    ii = dataItems.length;
                for (; i < ii; ++i)
                    (markersInfo[i] = markersInfo[i] || {}).coordinates = projection.parsePointData(dataItems[i].coordinates)
            },
            _createMarkers: function() {
                var self = this,
                    markersInfo = self._markersInfo = [];
                self._parseMarkers();
                var rootGroup = self._markersGroup,
                    shapesGroup = self._markerShapesGroup,
                    textsGroup = self._markerTextsGroup,
                    coversGroup = self._markerCoversGroup,
                    renderer = self._renderer,
                    themeManager = self._themeManager,
                    projection = self._projection,
                    dataItems = self._markersDataItems,
                    customizeCallback = self._markerCustomizeCallback,
                    markerInfo,
                    dataItem,
                    i = 0,
                    ii = markersInfo.length,
                    selectedList = [],
                    shape,
                    text,
                    cover;
                shapesGroup.applySettings(themeManager.getCommonMarkerSettings().common);
                textsGroup.applySettings(themeManager.getCommonMarkerSettings().text);
                themeManager.getCommonMarkerSettings().normal.filter = self._markerShadowFilter.ref;
                for (; i < ii; ++i) {
                    markerInfo = markersInfo[i];
                    dataItem = dataItems[i];
                    markerInfo.attributes = dataItem.attributes = dataItem.attributes || {};
                    markerInfo.options = (customizeCallback ? customizeCallback.call(dataItem, dataItem) : null) || {};
                    markerInfo.styles = themeManager.getMarkerSettings(markerInfo.options);
                    shape = text = cover = null;
                    markerInfo.location = projection.projectPoint(markerInfo.coordinates);
                    markerInfo.index = i;
                    shape = renderer.createCircle(markerInfo.location.x, markerInfo.location.y, markerInfo.styles.size, markerInfo.styles.normal).append(shapesGroup);
                    setElementData(shape.$element, i);
                    if (markerInfo.options.text) {
                        text = renderer.createText(markerInfo.options.text, markerInfo.location.x, markerInfo.location.y).append(textsGroup);
                        cover = renderer.createRect().append(coversGroup);
                        setElementData(cover.$element, i)
                    }
                    markerInfo.shape = shape;
                    markerInfo.text = text;
                    markerInfo.cover = cover;
                    markerInfo.options.isSelected && selectedList.push(markerInfo);
                    markerInfo.proxy = new ElementProxy(self, markerInfo, {
                        type: 'marker',
                        setSelectionCallback: self._setMarkerSelection
                    })
                }
                shapesGroup.append(rootGroup);
                textsGroup.append(rootGroup);
                coversGroup.append(rootGroup);
                self._arrangeMarkers();
                ii = self._markerSelectionMode !== SELECTION_MODE_NONE ? selectedList.length : 0;
                i = ii > 0 && self._markerSelectionMode === SELECTION_MODE_SINGLE ? ii - 1 : 0;
                for (; i < ii; ++i)
                    self._setMarkerSelection(selectedList[i], true, FLAG_NO_CALLBACK);
                self._markersReady = true;
                self._raiseReady()
            },
            _arrangeMarkers: function() {
                var self = this,
                    markersInfo = self._markersInfo,
                    i,
                    ii = markersInfo.length,
                    markerInfo,
                    measureList = [],
                    measureItem,
                    textBox,
                    x,
                    y;
                for (i = 0; i < ii; ++i) {
                    markerInfo = markersInfo[i];
                    measureItem = null;
                    if (markerInfo.text) {
                        textBox = markerInfo.text.getBBox();
                        x = markerInfo.location.x;
                        y = markerInfo.location.y;
                        markerInfo.textOffsetX = _round(x - textBox.x + markerInfo.styles.size) + 2;
                        markerInfo.textOffsetY = _round(y - textBox.y - textBox.height / 2) - 1;
                        markerInfo.trackerOffsetX = markerInfo.textOffsetX + textBox.x - x - 1;
                        markerInfo.trackerOffsetY = markerInfo.textOffsetY + textBox.y - y - 1;
                        markerInfo.trackerWidth = textBox.width + 2;
                        markerInfo.trackerHeight = textBox.height + 2;
                        measureItem = {
                            text: {
                                x: x + markerInfo.textOffsetX,
                                y: y + markerInfo.textOffsetY
                            },
                            cover: {
                                x: x + markerInfo.trackerOffsetX,
                                y: y + markerInfo.trackerOffsetY,
                                width: markerInfo.trackerWidth,
                                height: markerInfo.trackerHeight
                            }
                        }
                    }
                    measureList.push(measureItem)
                }
                self._markerTextsGroup.detach();
                self._markerCoversGroup.detach();
                for (i = 0; i < ii; ++i) {
                    markerInfo = markersInfo[i];
                    if (markerInfo.text) {
                        measureItem = measureList[i];
                        markerInfo.text.applySettings(measureItem.text);
                        markerInfo.cover.applySettings(measureItem.cover)
                    }
                }
                self._markerTextsGroup.append(self._markersGroup);
                self._markerCoversGroup.append(self._markersGroup)
            },
            _redrawMarkers: function() {
                var markersInfo = this._markersInfo,
                    projection = this._projection,
                    markerInfo,
                    i = 0,
                    ii = markersInfo.length,
                    x,
                    y;
                for (; i < ii; ++i) {
                    markerInfo = markersInfo[i];
                    markerInfo.location = projection.projectPoint(markerInfo.coordinates);
                    x = markerInfo.location.x;
                    y = markerInfo.location.y;
                    markerInfo.shape.applySettings({
                        cx: x,
                        cy: y
                    });
                    markerInfo.extra && markerInfo.extra.applySettings({
                        cx: x,
                        cy: y
                    });
                    if (markerInfo.options.text) {
                        markerInfo.text.applySettings({
                            x: x + markerInfo.textOffsetX,
                            y: y + markerInfo.textOffsetY
                        });
                        markerInfo.cover.applySettings({
                            x: x + markerInfo.trackerOffsetX,
                            y: y + markerInfo.trackerOffsetY
                        })
                    }
                }
                this._DEBUG_markersRedrawn && this._DEBUG_markersRedrawn()
            },
            _applyTransform: function(redraw) {
                var self = this,
                    transform = self._projection.getTransform();
                self._areasGroup.applySettings(transform);
                self._markersGroup.applySettings(transform);
                if (redraw) {
                    self._redrawAreas();
                    self._redrawMarkers()
                }
            },
            _setAreaHover: function(info, state) {
                if (!this._areaHoverEnabled)
                    return;
                state && DX.utils.debug.assert(!info.hovered, 'Area is already hovered');
                !state && DX.utils.debug.assert(info.hovered, 'Area is not hovered');
                info.hovered = !!state;
                if (!info.selected) {
                    info.element.applySettings(info.styles[state ? 'hovered' : 'normal']);
                    state ? info.element.toForeground() : info.element.toBackground()
                }
            },
            _setMarkerHover: function(info, state) {
                if (!this._markerHoverEnabled)
                    return;
                state && DX.utils.debug.assert(!info.hovered, 'Marker is already hovered');
                !state && DX.utils.debug.assert(info.hovered, 'Marker is not hovered');
                info.hovered = !!state;
                var extra = info.extra;
                if (!info.selected)
                    if (info.hovered) {
                        if (!extra) {
                            extra = info.extra = this._renderer.createCircle(info.location.x, info.location.y, info.styles.extraSize, info.styles.extra);
                            setElementData(extra.$element, info.index)
                        }
                        info.shape.applySettings(info.styles.hovered);
                        extra.insertBefore(info.shape)
                    }
                    else {
                        info.shape.applySettings(info.styles.normal);
                        extra.detach();
                        extra.dispose();
                        info.extra = null
                    }
            },
            _setAreaSelection: function(info, state, flag) {
                state && DX.utils.debug.assert(!info.selected, 'Area is already selected');
                !state && DX.utils.debug.assert(info.selected, 'Area is not selected');
                var self = this;
                if (self._areaSelectionMode === SELECTION_MODE_NONE)
                    return;
                info.selected = !!state;
                info.element.applySettings(info.styles[state ? 'selected' : info.hovered ? 'hovered' : 'normal']);
                if (info.selected)
                    !info.hovered && info.element.toForeground();
                else
                    !info.hovered && info.element.toBackground();
                if (!(flag & FLAG_NO_CALLBACK) && self._areaSelectionChangedCallback)
                    self._areaSelectionChangedCallback.call(info.proxy, info.proxy);
                if (!(flag & FLAG_NO_CHECK))
                    if (self._areaSelectionMode === SELECTION_MODE_SINGLE) {
                        info.selected && self._selectedAreas && self._setAreaSelection(self._selectedAreas, false, flag | FLAG_NO_CHECK);
                        self._selectedAreas = info.selected ? info : null
                    }
                    else
                        info.selected ? self._selectedAreas[info.index] = info : delete self._selectedAreas[info.index]
            },
            _setMarkerSelection: function(info, state, flag) {
                state && DX.utils.debug.assert(!info.selected, 'Marker is already selected');
                !state && DX.utils.debug.assert(info.selected, 'Marker is not selected');
                var self = this;
                if (self._markerSelectionMode === SELECTION_MODE_NONE)
                    return;
                info.selected = !!state;
                var extra = info.extra;
                if (info.selected) {
                    if (!extra) {
                        extra = info.extra = self._renderer.createCircle(info.location.x, info.location.y, info.styles.extraSize, info.styles.extra);
                        setElementData(extra.$element, info.index)
                    }
                    info.shape.applySettings(info.styles.selected);
                    extra.insertBefore(info.shape)
                }
                else if (info.hovered)
                    info.shape.applySettings(info.styles.hovered);
                else {
                    info.shape.applySettings(info.styles.normal);
                    extra.detach();
                    extra.dispose();
                    info.extra = null
                }
                if (!(flag & FLAG_NO_CALLBACK) && self._markerSelectionChangedCallback)
                    self._markerSelectionChangedCallback.call(info.proxy, info.proxy);
                if (!(flag & FLAG_NO_CHECK))
                    if (self._markerSelectionMode === SELECTION_MODE_SINGLE) {
                        info.selected && self._selectedMarkers && self._setMarkerSelection(self._selectedMarkers, false, flag | FLAG_NO_CHECK);
                        self._selectedMarkers = info.selected ? info : null
                    }
                    else
                        info.selected ? self._selectedMarkers[info.index] = info : delete self._selectedMarkers[info.index]
            },
            render: function(mode) {
                if (mode === 'resize')
                    this._resize();
                else
                    this._refresh();
                return this
            },
            getAreas: function() {
                var infos = this._areasInfo,
                    i = 0,
                    ii = infos.length,
                    list = [];
                for (; i < ii; ++i)
                    list.push(infos[i].proxy);
                return list
            },
            getMarkers: function() {
                var infos = this._markersInfo,
                    i = 0,
                    ii = infos.length,
                    list = [];
                for (; i < ii; ++i)
                    list.push(infos[i].proxy);
                return list
            },
            clearAreaSelection: function() {
                var self = this,
                    selectedAreas = self._selectedAreas;
                if (self._areaSelectionMode === SELECTION_MODE_SINGLE)
                    selectedAreas && self._setAreaSelection(selectedAreas, false);
                else if (self._areaSelectionMode === SELECTION_MODE_MULTIPLE) {
                    var key;
                    for (key in selectedAreas)
                        self._setAreaSelection(selectedAreas[key], false)
                }
                return self
            },
            clearMarkerSelection: function() {
                var self = this,
                    selectedMarkers = self._selectedMarkers;
                if (self._markerSelectionMode === SELECTION_MODE_SINGLE)
                    selectedMarkers && self._setMarkerSelection(selectedMarkers, false);
                else if (self._markerSelectionMode === SELECTION_MODE_MULTIPLE) {
                    var key;
                    for (key in selectedMarkers)
                        self._setMarkerSelection(selectedMarkers[key], false)
                }
                return self
            },
            clearSelection: function() {
                return this.clearAreaSelection().clearMarkerSelection()
            }
        });
        function setElementData($element, index) {
            $element.data('index', index)
        }
        function getElementData($element) {
            return $element.data('index')
        }
        function controlResetCallback() {
            var zoom = this._projection.getZoom();
            this._projection.setCenter(null).setZoom(null);
            this._applyTransform(zoom !== this._projection.getZoom())
        }
        function controlMoveCallback(dx, dy) {
            this._projection.moveCenter(dx, dy);
            this._applyTransform()
        }
        function controlZoomCallback(zoom) {
            this._projection.setZoom(zoom);
            this._applyTransform(true)
        }
        function startCallback(arg) {
            arg.data = getElementData(arg.$target);
            this._controlBar.processStart(arg)
        }
        function moveCallback(arg) {
            arg.data = getElementData(arg.$target);
            this._controlBar.processMove(arg)
        }
        function endCallback(arg) {
            arg.data = getElementData(arg.$target);
            this._controlBar.processEnd(arg)
        }
        function wheelCallback(arg) {
            this._controlBar.processWheel(arg)
        }
        function hoverOnCallback(arg) {
            var index = getElementData(arg.$target);
            switch (arg.category) {
                case'areas':
                    this._setAreaHover(this._areasInfo[index], true);
                    break;
                case'markers':
                    this._setMarkerHover(this._markersInfo[index], true);
                    break;
                default:
                    DX.utils.debug.assert(false, 'Unknown hover-on category!');
                    break
            }
        }
        function hoverOffCallback(arg) {
            var index = getElementData(arg.$target);
            switch (arg.category) {
                case'areas':
                    this._setAreaHover(this._areasInfo[index], false);
                    break;
                case'markers':
                    this._setMarkerHover(this._markersInfo[index], false);
                    break;
                default:
                    DX.utils.debug.assert(false, 'Unknown hover-off category!');
                    break
            }
        }
        function clickCallback(arg) {
            var map = this,
                index = getElementData(arg.$target),
                callback,
                proxy;
            switch (arg.category) {
                case'areas':
                    callback = map._areaClickCallback;
                    proxy = map._areasInfo[index].proxy;
                    break;
                case'markers':
                    callback = map._markerClickCallback;
                    proxy = map._markersInfo[index].proxy;
                    break;
                default:
                    DX.utils.debug.assert(false, 'Unknown click category!');
                    break
            }
            callback && callback.call(proxy, proxy)
        }
        function checkTooltipCallback(arg) {
            var index = getElementData(arg.$target),
                info;
            switch (arg.category) {
                case'areas':
                    info = this._areasInfo[index];
                    break;
                case'markers':
                    info = this._markersInfo[index];
                    break;
                default:
                    DX.utils.debug.assert(false, 'Unknown tooltip-check category!');
                    break
            }
            return this._tooltip.check(info.proxy)
        }
        function showTooltipCallback() {
            this._tooltip.show()
        }
        function moveTooltipCallback(arg) {
            var offset = _getRootOffset(this._renderer);
            this._tooltip.move({
                x: arg.x - offset.left,
                y: arg.y - offset.top
            })
        }
        function hideTooltipCallback() {
            this._tooltip.hide()
        }
        var ThemeManager = DX.Class.inherit({
                dispose: function() {
                    var self = this;
                    self._inner && self._inner.dispose();
                    self._inner = self._theme = null;
                    return self
                },
                setTheme: function(theme) {
                    var self = this;
                    if (!self._inner || self._tag !== theme) {
                        self._tag = theme;
                        self._inner && self._inner.dispose();
                        self._inner = new DX.viz.core.BaseThemeManager(theme, 'map');
                        self._theme = self._inner.theme;
                        self._inner.initializeFont(self._theme.marker.font);
                        self._inner.initializeFont(self._theme.tooltip.font);
                        self._inner.initializeFont(self._theme.legend.font)
                    }
                    return self
                },
                reset: function() {
                    this._commonAreaSettings = this._commonMarkerSettings = this._palette = null;
                    return this
                },
                getBackgroundSettings: function(options) {
                    var theme = this._theme.background,
                        merged = _extend({}, theme, options);
                    return {
                            strokeWidth: theme.borderWidth,
                            stroke: merged.borderColor,
                            fill: merged.color
                        }
                },
                initCommonAreaSettings: function(options) {
                    var theme = this._theme.area,
                        merged = _extend({}, theme, options);
                    this._commonAreaSettings = {
                        common: {
                            strokeWidth: theme.borderWidth,
                            stroke: merged.borderColor,
                            fill: merged.color
                        },
                        normal: {
                            'class': null,
                            strokeWidth: null,
                            stroke: null,
                            fill: null
                        },
                        hovered: {
                            'class': merged.hoveredClass,
                            strokeWidth: theme.hoveredBorderWidth,
                            stroke: merged.hoveredBorderColor,
                            fill: merged.hoveredColor
                        },
                        selected: {
                            'class': merged.selectedClass,
                            strokeWidth: theme.selectedBorderWidth,
                            stroke: merged.selectedBorderColor,
                            fill: merged.selectedColor
                        }
                    };
                    this._palette = new ContinuousPalette(merged.palette, merged.paletteSize);
                    this._DEBUG_palette = this._palette;
                    return this
                },
                getCommonAreaSettings: function() {
                    return this._commonAreaSettings
                },
                getAreaSettings: function(options) {
                    options = options || {};
                    if (options.color === undefined && options.paletteIndex >= 0)
                        options.color = this._palette.getColor(options.paletteIndex) || undefined;
                    var settings = this._commonAreaSettings;
                    return {
                            normal: getPartialSettings(settings.normal, options, AREA_PARTIAL_SETTINGS),
                            hovered: getPartialSettings(settings.hovered, options, HOVERED_AREA_PARTIAL_SETTINGS),
                            selected: getPartialSettings(settings.selected, options, SELECTED_AREA_PARTIAL_SETTINGS)
                        }
                },
                initCommonMarkerSettings: function(options) {
                    var theme = this._theme.marker,
                        merged = _extend({}, theme, options);
                    this._commonMarkerSettings = {
                        size: merged.size,
                        extraSize: merged.extraSize,
                        common: {
                            strokeWidth: theme.borderWidth,
                            stroke: merged.borderColor,
                            fill: merged.color
                        },
                        text: {
                            strokeWidth: 0,
                            stroke: 'none',
                            fill: 'none',
                            font: _extend({}, theme.font, merged.font)
                        },
                        normal: {
                            'class': null,
                            stroke: null,
                            fill: null
                        },
                        hovered: {
                            'class': merged.hoveredClass,
                            stroke: merged.hoveredBorderColor,
                            fill: merged.hoveredColor
                        },
                        selected: {
                            'class': merged.selectedClass,
                            stroke: merged.selectedBorderColor,
                            fill: merged.selectedColor
                        },
                        extra: {
                            strokeWidth: 0,
                            stroke: 'none',
                            fill: theme.extraColor,
                            opacity: theme.extraOpacity
                        }
                    };
                    return this
                },
                getCommonMarkerSettings: function() {
                    return this._commonMarkerSettings
                },
                getMarkerSettings: function(options) {
                    options = options || {};
                    var settings = this._commonMarkerSettings;
                    return {
                            size: options.size !== undefined ? options.size : settings.size,
                            extraSize: options.extraSize !== undefined ? options.extraSize : settings.extraSize,
                            normal: getPartialSettings(settings.normal, options, MARKER_PARTIAL_SETTINGS),
                            hovered: getPartialSettings(settings.hovered, options, HOVERED_MARKER_PARTIAL_SETTINGS),
                            selected: getPartialSettings(settings.selected, options, SELECTED_MARKER_PARTIAL_SETTINGS),
                            extra: settings.extra
                        }
                },
                getControlBarSettings: function(options) {
                    var theme = this._theme.controlBar,
                        merged = _extend({}, theme, options);
                    return _extend({}, options, {shape: {
                                strokeWidth: theme.borderWidth,
                                stroke: merged.borderColor,
                                fill: merged.color
                            }})
                },
                getTooltipSettings: function(options) {
                    var theme = this._theme.tooltip,
                        merged = _extend({}, theme, options);
                    return _extend({}, options, {
                            shape: {
                                strokeWidth: theme.borderWidth,
                                stroke: merged.borderColor,
                                fill: merged.color
                            },
                            text: {
                                strokeWidth: 0,
                                stroke: 'none',
                                fill: 'none',
                                font: _extend({}, theme.font, merged.font)
                            }
                        })
                },
                getLegendSettings: function(options) {
                    var theme = this._theme.legend,
                        merged = _extend({}, theme, options);
                    return _extend({}, options, {
                            background: {
                                strokeWidth: theme.borderWidth,
                                stroke: merged.borderColor,
                                fill: merged.color,
                                opacity: theme.opacity
                            },
                            text: {
                                strokeWidth: 0,
                                stroke: 'none',
                                fill: 'none',
                                align: 'left',
                                font: _extend({}, theme.font, merged.font),
                                'class': 'dxm-legend-text'
                            },
                            metrics: {
                                horizontalIndent: theme.horizontalIndent,
                                verticalIndent: theme.verticalIndent,
                                horizontalPadding: merged.horizontalPadding,
                                verticalPadding: merged.verticalPadding,
                                textIndent: merged.textIndent,
                                itemSize: merged.itemSize,
                                itemSpacing: merged.itemSpacing,
                                maxWidth: merged.maxWidth,
                                maxHeight: merged.maxHeight
                            }
                        })
                },
                getLegendItemSettings: function(item) {
                    var color = item.color;
                    if (color === undefined && item.paletteIndex >= 0)
                        color = this._palette.getColor(item.paletteIndex);
                    return {
                            strokeWidth: 0,
                            stroke: 'none',
                            fill: color
                        }
                }
            });
        var AREA_PARTIAL_SETTINGS = {
                color: 'fill',
                borderColor: 'stroke'
            },
            HOVERED_AREA_PARTIAL_SETTINGS = {
                hoveredColor: 'fill',
                hoveredBorderColor: 'stroke',
                hoveredClass: 'class'
            },
            SELECTED_AREA_PARTIAL_SETTINGS = {
                selectedColor: 'fill',
                selectedBorderColor: 'stroke',
                selectedClass: 'class'
            },
            MARKER_PARTIAL_SETTINGS = {
                color: 'fill',
                borderColor: 'stroke'
            },
            HOVERED_MARKER_PARTIAL_SETTINGS = {
                hoveredColor: 'fill',
                hoveredBorderColor: 'stroke',
                hoveredClass: 'class'
            },
            SELECTED_MARKER_PARTIAL_SETTINGS = {
                selectedColor: 'fill',
                selectedBorderColor: 'stroke',
                selectedClass: 'class'
            };
        function getPartialSettings(common, partial, map) {
            var name,
                count = 0,
                cache = {};
            for (name in map)
                if (partial[name] !== undefined) {
                    ++count;
                    cache[map[name]] = partial[name]
                }
            return count ? _extend({}, common, cache) : common
        }
        var palettes = {
                'default': {
                    start: '#5f8b95',
                    end: '#ba4d51'
                },
                'soft pastel': {
                    start: '#92c7e2',
                    end: '#f2ca84'
                },
                'harmony light': {
                    start: '#a6c567',
                    end: '#fcb65e'
                },
                pastel: {
                    start: '#bb7862',
                    end: '#a4d5c2'
                },
                bright: {
                    start: '#e97f02',
                    end: '#f8ca00'
                },
                soft: {
                    start: '#9ab57e',
                    end: '#e8c267'
                },
                ocean: {
                    start: '#00a7c6',
                    end: '#378a8a'
                },
                vintage: {
                    start: '#f2c0b5',
                    end: '#a85c4c'
                },
                violet: {
                    start: '#d1a1d1',
                    end: '#7b5685'
                }
            };
        function ContinuousPalette(source, size) {
            var palette = source && source.start && source.end ? source : palettes[_String(source).toLowerCase()] || palettes['default'];
            palette = size > 0 ? createPaletteColors(palette.start, palette.end, _Number(size)) : [];
            this.getColor = function(index) {
                return palette[index] || null
            };
            this._DEBUG_source = source;
            this._DEBUG_size = size
        }
        function createPaletteColors(start, end, count) {
            var startColor = new _Color(start),
                endColor = new _Color(end);
            if (count === 1)
                return [startColor.blend(endColor, 0.5).toHex()];
            else {
                var list = [],
                    step = 1 / (count - 1),
                    i,
                    ii = count;
                list.push(0);
                for (i = 1; i < ii - 1; ++i)
                    list.push(step * i);
                list.push(1);
                for (i = 0; i < ii; ++i)
                    list[i] = startColor.blend(endColor, list[i]).toHex();
                return list
            }
        }
        DX.viz.map._tests.ThemeManager = ThemeManager;
        DX.viz.map._tests.ContinuousPalette = ContinuousPalette;
        DX.viz.map._tests.palettes = palettes;
        DX.viz.map.Map.include({_themeManagerType: ThemeManager});
        var DOUBLE_PI = Math.PI * 2,
            HALF_PI = Math.PI / 2,
            QUARTER_PI = Math.PI / 4,
            PI_TO_180 = Math.PI / 180;
        var ASPECT_RATIO = 1,
            MIN_LON = -180,
            MAX_LON = 180,
            MIN_LAT = -90,
            MAX_LAT = 90;
        var Projection = DX.Class.inherit({
                setBounds: function(bounds) {
                    bounds = bounds || {};
                    var self = this;
                    self._minlon = bounds.minLon >= MIN_LON ? _Number(bounds.minLon) : MIN_LON;
                    self._maxlon = bounds.maxLon <= MAX_LON ? _Number(bounds.maxLon) : MAX_LON;
                    self._minlat = bounds.minLat >= MIN_LAT ? _Number(bounds.minLat) : MIN_LAT;
                    self._maxlat = bounds.maxLat <= MAX_LAT ? _Number(bounds.maxLat) : MAX_LAT;
                    return self
                },
                setSize: function(width, height) {
                    var self = this;
                    self._width = width;
                    self._height = height;
                    self._setupBounds();
                    self._adjustZoom();
                    self._adjustCenter();
                    return self
                },
                _setupBounds: function() {
                    var self = this,
                        width = self._width,
                        height = self._height,
                        size = height / width;
                    size = size <= ASPECT_RATIO ? height : width;
                    self._radius = size / DOUBLE_PI;
                    self._x0 = width / 2;
                    self._y0 = height / 2;
                    self._miny = self._y0 - size / 2;
                    self._maxy = self._y0 + size / 2;
                    if (self._maxlon - self._minlon >= 360 && self._maxlat - self._minlat >= 180)
                        return;
                    var coords1 = self._project(self._minlon, self._maxlat),
                        coords2 = self._project(self._maxlon, self._minlat),
                        xratio = width / (coords2.x - coords1.x),
                        yratio = height / (coords2.y - coords1.y),
                        ratio = xratio;
                    if (xratio < yratio) {
                        ratio = xratio;
                        xratio = (coords1.y + coords2.y) / 2;
                        yratio = height / ratio / 2;
                        coords1.y = xratio - yratio;
                        coords2.y = xratio + yratio
                    }
                    else if (xratio > yratio) {
                        ratio = yratio;
                        yratio = (coords1.x + coords2.x) / 2;
                        xratio = width / ratio / 2;
                        coords1.x = yratio - xratio;
                        coords2.x = yratio + xratio
                    }
                    self._x0 = -coords1.x * ratio + width * ratio / 2;
                    self._y0 = -coords1.y * ratio + height * ratio / 2;
                    self._radius *= ratio;
                    size *= ratio;
                    self._miny = self._y0 - size / 2;
                    self._maxy = self._y0 + size / 2
                },
                _project: function(lon, lat, noTruncate) {
                    var self = this,
                        lon_ = lon * PI_TO_180,
                        lat_,
                        x = self._radius * lon_ + self._x0,
                        y;
                    if (lat <= MIN_LAT)
                        y = self._maxy;
                    else if (lat >= MAX_LAT)
                        y = self._miny;
                    else {
                        lat_ = lat * PI_TO_180;
                        y = self._radius * -_ln(_tan(QUARTER_PI + lat_ / 2)) + self._y0
                    }
                    if (!noTruncate) {
                        y <= self._miny && (y = self._miny);
                        y >= self._maxy && (y = self._maxy)
                    }
                    return {
                            x: x,
                            y: y
                        }
                },
                _invproject: function(x, y) {
                    var self = this,
                        lon = (x - self._x0) / self._radius,
                        lat = 2 * _atan(_exp((self._y0 - y) / self._radius)) - HALF_PI;
                    return {
                            lat: lat / PI_TO_180,
                            lon: lon / PI_TO_180
                        }
                },
                parseAreaData: function(coordinates) {
                    var self = this,
                        i = 0,
                        ii = _isArray(coordinates) ? coordinates.length : 0,
                        area,
                        j,
                        jj,
                        x,
                        y,
                        points,
                        coords,
                        list = [];
                    for (; i < ii; ++i) {
                        area = coordinates[i];
                        j = 0;
                        jj = _isArray(area) ? area.length : 0;
                        if (jj) {
                            points = [];
                            for (; j < jj; ) {
                                coords = self._project(area[j++], area[j++]);
                                points.push(coords.x, coords.y)
                            }
                            list.push(points)
                        }
                    }
                    return list
                },
                parsePointData: function(coordinates) {
                    return this._project(coordinates[0], coordinates[1])
                },
                projectArea: function(data) {
                    var k = 0,
                        kk = data.length,
                        partialData,
                        i,
                        ii,
                        list = [],
                        partialPath,
                        zoom = this._zoom,
                        xzoom = this._xzoom,
                        yzoom = this._yzoom;
                    for (; k < kk; ++k) {
                        partialData = data[k];
                        partialPath = [];
                        for (i = 0, ii = partialData.length; i < ii; i += 2)
                            partialPath.push(zoom * partialData[i] - xzoom, zoom * partialData[i + 1] - yzoom);
                        list.push(_buildPath(partialPath))
                    }
                    return list.join(' ')
                },
                projectPoint: function(data) {
                    return {
                            x: _round(this._zoom * data.x - this._xzoom),
                            y: _round(this._zoom * data.y - this._yzoom)
                        }
                },
                _adjustZoom: function() {
                    var self = this;
                    self._xzoom = self._width * (self._zoom - 1) / 2;
                    self._yzoom = self._height * (self._zoom - 1) / 2
                },
                _adjustCenter: function() {
                    var self = this,
                        center = self._project(self._loncenter, self._latcenter, true);
                    self._dxcenter = (self._x0 - (self._xcenter = center.x)) * self._zoom;
                    self._dycenter = (self._y0 - (self._ycenter = center.y)) * self._zoom
                },
                getZoom: function() {
                    return this._zoom
                },
                setZoom: function(zoom) {
                    var self = this,
                        _zoom = _Number(zoom);
                    _zoom < MIN_ZOOM && (_zoom = MIN_ZOOM);
                    _zoom > MAX_ZOOM && (_zoom = MAX_ZOOM);
                    self._zoom = MIN_ZOOM <= _zoom && _zoom <= MAX_ZOOM ? _zoom : 1;
                    self._adjustZoom();
                    self._adjustCenter();
                    return self
                },
                setCenter: function(center) {
                    center = center || {};
                    this._latcenter = _Number(center.lat) || 0;
                    this._loncenter = _Number(center.lon) || 0;
                    this._adjustCenter();
                    return this
                },
                moveCenter: function(screenDx, screenDy) {
                    var self = this,
                        newx = self._xcenter + screenDx / self._zoom,
                        newy = self._ycenter + screenDy / self._zoom,
                        coords = self._invproject(newx, newy);
                    return self.setCenter(coords)
                },
                getTransform: function() {
                    return {
                            translateX: this._dxcenter,
                            translateY: this._dycenter
                        }
                }
            });
        DX.viz.map._tests.Projection = Projection;
        DX.viz.map.Map.include({_projectionType: Projection});
        var _document = $(window.document),
            _now = $.now,
            _addNamespace = DX.ui.events.addNamespace,
            EVENT_NAMESPACE = 'dxVectorMap',
            EVENT_NAMES = {},
            EVENT_MODE,
            REQUIRED_STYLE_ON,
            REQUIRED_STYLE_OFF,
            isTouchEvent;
        setupEvents();
        function setupEvents() {
            var wnd = window,
                isPointer = wnd.navigator.pointerEnabled,
                isMSPointer = wnd.navigator.msPointerEnabled,
                isTouch = 'ontouchstart' in wnd;
            switch (arguments[0]) {
                case'pointer':
                    isPointer = true;
                    isMSPointer = isTouch = false;
                    break;
                case'MSPointer':
                    isMSPointer = true;
                    isPointer = isTouch = false;
                    break;
                case'touch':
                    isTouch = true;
                    isPointer = isMSPointer = false;
                    break;
                case'mouse':
                    isPointer = isMSPointer = isTouch = false;
                    break
            }
            EVENT_NAMES.start = _addNamespace(isPointer ? 'pointerdown' : isMSPointer ? 'MSPointerDown' : isTouch ? 'touchstart mousedown' : 'mousedown', EVENT_NAMESPACE);
            EVENT_NAMES.move = _addNamespace(isPointer ? 'pointermove' : isMSPointer ? 'MSPointerMove' : isTouch ? 'touchmove mousemove' : 'mousemove', EVENT_NAMESPACE);
            EVENT_NAMES.end = _addNamespace(isPointer ? 'pointerup' : isMSPointer ? 'MSPointerUp' : isTouch ? 'touchend mouseup' : 'mouseup', EVENT_NAMESPACE);
            EVENT_NAMES.over = _addNamespace(isPointer ? 'pointerover' : isMSPointer ? 'MSPointerOver' : 'mouseover', EVENT_NAMESPACE);
            EVENT_NAMES.out = _addNamespace(isPointer ? 'pointerout' : isMSPointer ? 'MSPointerOut' : 'mouseout', EVENT_NAMESPACE);
            EVENT_NAMES.wheel = _addNamespace('mousewheel DOMMouseScroll', EVENT_NAMESPACE);
            if (isPointer) {
                EVENT_MODE = 'pointer';
                REQUIRED_STYLE_ON = {'touch-action': 'none'};
                REQUIRED_STYLE_OFF = {'touch-action': ''};
                isTouchEvent = function(event) {
                    return event.originalEvent.pointerType !== 'mouse'
                }
            }
            else if (isMSPointer) {
                EVENT_MODE = 'MSPointer';
                REQUIRED_STYLE_ON = {'-ms-touch-action': 'none'};
                REQUIRED_STYLE_OFF = {'-ms-touch-action': ''};
                isTouchEvent = function(event) {
                    return event.originalEvent.pointerType !== 4
                }
            }
            else if (isTouch) {
                EVENT_MODE = 'touch';
                REQUIRED_STYLE_ON = {'-webkit-user-select': 'none'};
                REQUIRED_STYLE_OFF = {'-webkit-user-select': ''};
                isTouchEvent = function() {
                    return true
                }
            }
            else {
                EVENT_MODE = 'mouse';
                REQUIRED_STYLE_ON = {};
                REQUIRED_STYLE_OFF = {};
                isTouchEvent = function() {
                    return false
                }
            }
        }
        function getEventCoords(event) {
            var originalEvent = event.originalEvent,
                touch = originalEvent.changedTouches ? originalEvent.changedTouches[0] : {};
            return {
                    x: event.pageX || originalEvent.pageX || touch.pageX,
                    y: event.pageY || originalEvent.pageY || touch.pageY
                }
        }
        var EVENT_START = 'start',
            EVENT_MOVE = 'move',
            EVENT_END = 'end',
            EVENT_WHEEL = 'wheel',
            EVENT_HOVER_ON = 'hover-on',
            EVENT_HOVER_OFF = 'hover-off',
            EVENT_CLICK = 'click',
            EVENT_TOOLTIP_CHECK = 'tooltip-check',
            EVENT_TOOLTIP_SHOW = 'tooltip-show',
            EVENT_TOOLTIP_HIDE = 'tooltip-hide',
            EVENT_TOOLTIP_MOVE = 'tooltip-move';
        var Tracker = DX.Class.inherit({
                ctor: function() {
                    var self = this;
                    self._groups = {};
                    self._createCallbacks();
                    self._resetState()
                },
                dispose: function() {
                    var self = this;
                    DX.utils.debug.assert(!self._root, 'Undetached root!');
                    DX.utils.debug.assert($.map(self._groups, function(item) {
                        return item
                    }).length === 0, 'Undetached groups!');
                    self._dispose();
                    self._groups = self._context = self._callbacks = null;
                    return self
                },
                _resetState: function() {
                    var self = this;
                    _clearTimeout(self._tooltip_showTimeout);
                    _clearTimeout(self._tooltip_hideTimeout);
                    self._moving = self._click_time = self._hover_event = self._tooltip_target = self._tooltip_showTimeout = self._tooltip_hideTimeout = null
                },
                _createCallbacks: function() {
                    var self = this;
                    self._rootEvents = {};
                    self._rootEvents[EVENT_NAMES.start] = function(event) {
                        var isTouch = isTouchEvent(event);
                        if (isTouch && !self._touchEnabled)
                            return;
                        event.preventDefault();
                        self._processStart(event);
                        isTouch && self._processTooltipRootTouchStart(event)
                    };
                    self._documentEventsMoveEnd = {};
                    self._documentEventsMoveEnd[EVENT_NAMES.move] = function(event) {
                        self._processMove(event)
                    };
                    self._documentEventsMoveEnd[EVENT_NAMES.end] = function(event) {
                        self._processEnd(event)
                    };
                    self._rootEvents[EVENT_NAMES.wheel] = function(event) {
                        if (self._wheelEnabled) {
                            event.preventDefault();
                            self._processWheel(event)
                        }
                    };
                    self._groupEvents = {};
                    self._groupEvents[EVENT_NAMES.start] = function(event) {
                        var isTouch = isTouchEvent(event);
                        if (isTouch && !self._touchEnabled)
                            return;
                        self._processClickStart(event);
                        isTouch && self._processTooltipTouchStart(event)
                    };
                    self._groupClickEventsEnd = {};
                    self._groupClickEventsEnd[EVENT_NAMES.end] = function(event) {
                        self._processClickEnd(event)
                    };
                    self._groupEvents[EVENT_NAMES.over] = function(event) {
                        if (isTouchEvent(event))
                            return;
                        self._processHoverOn(event);
                        self._processTooltipMouseOver(event)
                    };
                    self._groupEvents[EVENT_NAMES.out] = function(event) {
                        if (isTouchEvent(event))
                            return;
                        self._processHoverOff(event);
                        self._processTooltipMouseOut(event)
                    };
                    self._groupTooltipEventsMouseMove = {};
                    self._groupTooltipEventsMouseMove[EVENT_NAMES.move] = function(event) {
                        self._processTooltipMouseMove(event)
                    };
                    self._groupTooltipEventsTouchMoveEnd = {};
                    self._groupTooltipEventsTouchMoveEnd[EVENT_NAMES.move] = function(event) {
                        self._processTooltipTouchMove(event)
                    };
                    self._groupTooltipEventsTouchMoveEnd[EVENT_NAMES.end] = function(event) {
                        self._processTooltipTouchEnd(event)
                    };
                    self._showTooltipCallback = function() {
                        self._showTooltipCore()
                    };
                    self._hideTooltipCallback = function() {
                        self._hideTooltipCore()
                    };
                    self._dispose = function() {
                        var self = this;
                        self = self._dispose = self._rootEvents = self._documentEventsMoveEnd = self._groupEvents = self._groupClickEventsEnd = self._groupTooltipEventsMouseMove = self._groupTooltipEventsTouchMoveEnd = self._showTooltipCallback = self._hideTooltipCallback = null
                    }
                },
                _processStart: function(event) {
                    var self = this,
                        coords = getEventCoords(event);
                    self._start_x = self._x = coords.x;
                    self._start_y = self._y = coords.y;
                    self._callbacks[EVENT_START].call(self._context, {
                        $target: $(event.target),
                        x: self._x,
                        y: self._y
                    });
                    _document.off(self._documentEventsMoveEnd).on(self._documentEventsMoveEnd, event.data)
                },
                _processMove: function(event) {
                    var self = this,
                        coords = getEventCoords(event);
                    if (self._moving || _abs(self._start_x - coords.x) > 3 || _abs(self._start_y - coords.y) > 3) {
                        self._moving = true;
                        self._x = coords.x;
                        self._y = coords.y;
                        self._callbacks[EVENT_MOVE].call(self._context, {
                            $target: $(event.target),
                            x: self._x,
                            y: self._y
                        })
                    }
                },
                _processEnd: function(event) {
                    var self = this;
                    _document.off(self._documentEventsMoveEnd);
                    self._callbacks[EVENT_END].call(self._context, {
                        $target: $(event.target),
                        x: self._x,
                        y: self._y
                    });
                    self._moving = self._start_x = self._start_y = self._x = self._y = null
                },
                _processWheel: function(event) {
                    var delta = event.originalEvent.wheelDelta / 120 || event.originalEvent.detail / -3 || 0;
                    this._callbacks[EVENT_WHEEL].call(this._context, {
                        $target: $(event.target),
                        delta: delta
                    })
                },
                _processHoverOn: function(event) {
                    var self = this;
                    if (self._hover_event && self._hover_event.target === event.target)
                        return;
                    self._hover_event && self._callbacks[EVENT_HOVER_OFF].call(self._context, {
                        $target: $(self._hover_event.target),
                        category: self._hover_event.data.category
                    });
                    self._hover_event = event;
                    self._callbacks[EVENT_HOVER_ON].call(self._context, {
                        $target: $(self._hover_event.target),
                        category: self._hover_event.data.category
                    })
                },
                _processHoverOff: function(event) {
                    var self = this;
                    if (getElementData($(event.target)) === undefined)
                        return;
                    self._hover_event && self._callbacks[EVENT_HOVER_OFF].call(self._context, {
                        $target: $(self._hover_event.target),
                        category: self._hover_event.data.category
                    });
                    self._hover_event = null
                },
                _processClickStart: function(event) {
                    this._click_time = _now();
                    event.data.container.off(this._groupClickEventsEnd).on(this._groupClickEventsEnd, event.data)
                },
                _processClickEnd: function(event) {
                    var self = this;
                    if (self._click_time && !self._moving && _now() - self._click_time <= 500)
                        self._callbacks[EVENT_CLICK].call(self._context, {
                            $target: $(event.target),
                            category: event.data.category
                        });
                    self._click_time = null;
                    event.data.container.off(self._groupClickEventsEnd)
                },
                _processTooltipMouseOver: function(event) {
                    var self = this;
                    if (self._tooltipEnabled && self._isTooltipAvailable(event)) {
                        var coords = getEventCoords(event);
                        self._tooltip_x = coords.x;
                        self._tooltip_y = coords.y;
                        event.data.container.off(self._groupTooltipEventsMouseMove).on(self._groupTooltipEventsMouseMove, event.data);
                        self._showTooltip(event, self._tooltip_target ? null : TOOLTIP_SHOW_DELAY)
                    }
                },
                _processTooltipMouseMove: function(event) {
                    var self = this;
                    if (self._isTooltipAvailable(event))
                        if (self._tooltip_target)
                            self._showTooltip(event);
                        else {
                            var coords = getEventCoords(event);
                            if (_abs(self._tooltip_x - coords.x) > 3 || _abs(self._tooltip_y - coords.y) > 3)
                                self._showTooltip(event, TOOLTIP_SHOW_DELAY)
                        }
                    else {
                        event.data.container.off(self._groupTooltipEventsMouseMove);
                        self._hideTooltip(TOOLTIP_HIDE_DELAY)
                    }
                },
                _processTooltipMouseOut: function(event) {
                    if (this._tooltipEnabled) {
                        event.data.container.off(this._groupTooltipEventsMouseMove);
                        this._hideTooltip(TOOLTIP_HIDE_DELAY)
                    }
                },
                _processTooltipTouchStart: function(event) {
                    var self = this;
                    if (self._tooltipEnabled && self._isTooltipAvailable(event)) {
                        self._showTooltip(event, TOOLTIP_TOUCH_SHOW_DELAY);
                        event.data.container.off(self._groupTooltipEventsTouchMoveEnd).on(self._groupTooltipEventsTouchMoveEnd, event.data);
                        self._skipTouchStart = true
                    }
                },
                _processTooltipRootTouchStart: function(event) {
                    if (!this._skipTouchStart)
                        this._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY);
                    this._skipTouchStart = null
                },
                _processTooltipTouchMove: function(event) {
                    if (this._moving) {
                        this._hideTooltip();
                        event.data.container.off(this._groupTooltipEventsTouchMoveEnd)
                    }
                },
                _processTooltipTouchEnd: function(event) {
                    if (this._tooltip_showTimeout)
                        this._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY);
                    event.data.container.off(this._groupTooltipEventsTouchMoveEnd)
                },
                _isTooltipAvailable: function(event) {
                    var self = this,
                        result = !self._moving;
                    if (result && (!self._tooltip_event || self._tooltip_event.target !== event.target))
                        result = self._callbacks[EVENT_TOOLTIP_CHECK].call(self._context, {
                            $target: $(event.target),
                            category: event.data.category
                        });
                    return result
                },
                _showTooltip: function(event, delay) {
                    var self = this;
                    _clearTimeout(self._tooltip_hideTimeout);
                    self._tooltip_hideTimeout = null;
                    _clearTimeout(self._tooltip_showTimeout);
                    self._tooltip_event = event;
                    if (delay > 0)
                        self._tooltip_showTimeout = _setTimeout(self._showTooltipCallback, delay);
                    else
                        self._showTooltipCallback()
                },
                _hideTooltip: function(delay) {
                    var self = this;
                    _clearTimeout(self._tooltip_showTimeout);
                    self._tooltip_showTimeout = null;
                    if (delay > 0)
                        self._tooltip_hideTimeout = self._tooltip_hideTimeout || _setTimeout(self._hideTooltipCallback, delay);
                    else {
                        _clearTimeout(self._tooltip_hideTimeout);
                        self._hideTooltipCallback()
                    }
                },
                _showTooltipCore: function() {
                    var self = this,
                        event = self._tooltip_event,
                        coords = getEventCoords(event);
                    if (!self._tooltip_target)
                        self._callbacks[EVENT_TOOLTIP_SHOW].call(self._context, {
                            $target: $(event.target),
                            category: event.data.category
                        });
                    self._tooltip_target = event.target;
                    self._callbacks[EVENT_TOOLTIP_MOVE].call(self._context, {
                        $target: $(self._tooltip_target),
                        category: event.data.category,
                        x: coords.x,
                        y: coords.y
                    });
                    self._tooltip_showTimeout = null
                },
                _hideTooltipCore: function() {
                    var self = this,
                        event = self._tooltip_event;
                    if (self._tooltip_target)
                        self._callbacks[EVENT_TOOLTIP_HIDE].call(self._context, {
                            $target: $(self._tooltip_target),
                            category: event.data.category
                        });
                    self._tooltip_target = self._tooltip_hideTimeout = self._tooltip_event = null
                },
                attachRoot: function(container) {
                    DX.utils.debug.assert(!this._root, 'Root is already attached!');
                    this._root = container;
                    return this
                },
                detachRoot: function() {
                    DX.utils.debug.assert(this._root, 'Root is not attached!');
                    this._root = null;
                    return this
                },
                attachGroup: function(category, container) {
                    DX.utils.debug.assert(!this._groups[category], 'Group category is already attached!');
                    this._groups[category] = container;
                    return this
                },
                detachGroup: function(category) {
                    DX.utils.debug.assert(this._groups[category], 'Group category is not attached!');
                    this._groups[category] = null;
                    return this
                },
                setCallbacks: function(context, callbacks) {
                    this._context = context;
                    this._callbacks = callbacks;
                    return this
                },
                setOptions: function(options) {
                    options = options || {};
                    var self = this;
                    self._enabled = options.enabled;
                    self._touchEnabled = options.touchEnabled;
                    self._wheelEnabled = options.wheelEnabled;
                    self._tooltipEnabled = options.tooltipEnabled;
                    return self
                },
                render: function() {
                    var self = this;
                    if (!self._enabled)
                        return self;
                    if (self._touchEnabled) {
                        if (EVENT_MODE === 'pointer' || EVENT_MODE === 'MSPointer')
                            self._root.on(_addNamespace('MSHoldVisual', EVENT_NAMESPACE), function(event) {
                                event.preventDefault()
                            });
                        self._root.applySettings({style: REQUIRED_STYLE_ON})
                    }
                    self._root.on(self._rootEvents, {container: self._root});
                    var category,
                        group;
                    for (category in self._groups) {
                        group = self._groups[category];
                        group && group.on(self._groupEvents, {
                            category: category,
                            container: group
                        })
                    }
                    return self
                },
                clean: function() {
                    var self = this;
                    if (!self._enabled)
                        return self;
                    if (self._touchEnabled)
                        self._root.applySettings({style: REQUIRED_STYLE_OFF});
                    self._root.off('.' + EVENT_NAMESPACE);
                    _document.off(self._documentEventsMoveEnd);
                    var category,
                        group;
                    for (category in self._groups) {
                        group = self._groups[category];
                        group && group.off('.' + EVENT_NAMESPACE)
                    }
                    self._resetState();
                    return self
                }
            });
        DX.viz.map._tests.Tracker = Tracker;
        DX.viz.map._tests._DEBUG_forceEventMode = function(mode) {
            setupEvents(mode)
        };
        DX.viz.map.Map.include({_trackerType: Tracker});
        var COMMAND_TO_TYPE_MAP = {};
        COMMAND_TO_TYPE_MAP[COMMAND_RESET] = ResetCommand;
        COMMAND_TO_TYPE_MAP[COMMAND_MOVE_UP] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_RIGHT] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_DOWN] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_LEFT] = MoveCommand;
        COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_IN] = COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_OUT] = ZoomCommand;
        COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_DRAG] = ZoomDragCommand;
        var ControlBar = DX.Class.inherit({
                ctor: function(parameters) {
                    var self = this;
                    self._container = parameters.container;
                    self._createElements(parameters.renderer);
                    var context = parameters.context,
                        resetCallback = parameters.resetCallback,
                        moveCallback = parameters.moveCallback,
                        zoomCallback = parameters.zoomCallback;
                    self._reset = function() {
                        resetCallback.call(context)
                    };
                    self._move = function(dx, dy) {
                        moveCallback.call(context, dx, dy)
                    };
                    self._zoom = function(zoom) {
                        zoomCallback.call(context, zoom)
                    };
                    self._dispose = function() {
                        delete this._reset;
                        delete this._move;
                        delete this._zoom;
                        delete this._dispose;
                        context = resetCallback = moveCallback = zoomCallback = null
                    };
                    parameters = null
                },
                _createElements: function(renderer) {
                    var rootGroup = this._root = renderer.createGroup({'class': 'dxm-control-bar'}),
                        buttonsGroup = renderer.createGroup({'class': 'dxm-control-buttons'}).append(rootGroup),
                        trackersGroup = renderer.createGroup({
                            stroke: 'none',
                            strokeWidth: 0,
                            fill: '#000000',
                            opacity: 0.0001,
                            cursor: 'pointer'
                        }).append(rootGroup),
                        options = {
                            bigCircleSize: 58,
                            smallCircleSize: 28,
                            buttonSize: 10,
                            arrowButtonOffset: 20,
                            incdecButtonSize: 11,
                            incButtonOffset: 66,
                            decButtonOffset: 227,
                            sliderLineStartOffset: 88.5,
                            sliderLineEndOffset: 205.5,
                            sliderLength: 20,
                            sliderWidth: 8,
                            trackerGap: 4
                        };
                    this._buttonsGroup = buttonsGroup;
                    this._createButtons(renderer, buttonsGroup, options);
                    this._createTrackers(renderer, trackersGroup, options);
                    rootGroup.applySettings({
                        translateX: 50.5,
                        translateY: 50.5
                    })
                },
                _createButtons: function(renderer, group, options) {
                    var size = options.buttonSize / 2,
                        offset1 = options.arrowButtonOffset - size,
                        offset2 = options.arrowButtonOffset,
                        incdecButtonSize = options.incdecButtonSize / 2;
                    renderer.createCircle(0, 0, options.bigCircleSize / 2).append(group);
                    renderer.createCircle(0, 0, size).append(group);
                    renderer.createPath([-size, -offset1, 0, -offset2, size, -offset1]).append(group);
                    renderer.createPath([offset1, -size, offset2, 0, offset1, size]).append(group);
                    renderer.createPath([size, offset1, 0, offset2, -size, offset1]).append(group);
                    renderer.createPath([-offset1, size, -offset2, 0, -offset1, -size]).append(group);
                    renderer.createCircle(0, options.incButtonOffset, options.smallCircleSize / 2).append(group);
                    renderer.createSimplePath({d: _buildPath([-incdecButtonSize, options.incButtonOffset, incdecButtonSize, options.incButtonOffset]) + ' ' + _buildPath([0, options.incButtonOffset - incdecButtonSize, 0, options.incButtonOffset + incdecButtonSize])}).append(group);
                    renderer.createCircle(0, options.decButtonOffset, options.smallCircleSize / 2).append(group);
                    renderer.createSimplePath({d: _buildPath([-incdecButtonSize, options.decButtonOffset, incdecButtonSize, options.decButtonOffset])}).append(group);
                    renderer.createSimplePath({d: _buildPath([0, options.sliderLineStartOffset, 0, options.sliderLineEndOffset])}).append(group);
                    this._zoomDrag = renderer.createRect(-options.sliderLength / 2, options.sliderLineEndOffset - options.sliderWidth / 2, options.sliderLength, options.sliderWidth).append(group);
                    this._zoomCoeff = (options.sliderLineEndOffset - options.sliderLineStartOffset) / 5
                },
                _createTrackers: function(renderer, group, options) {
                    var size = _round((options.arrowButtonOffset - options.trackerGap) / 2),
                        offset1 = options.arrowButtonOffset - size,
                        offset2 = _round(_pow(options.bigCircleSize * options.bigCircleSize / 4 - size * size, 0.5)),
                        size2 = offset2 - offset1,
                        element;
                    element = renderer.createRect(-size, -size, size * 2, size * 2).append(group);
                    setElementData(element.$element, COMMAND_RESET);
                    element = renderer.createRect(-size, -offset2, size * 2, size2).append(group);
                    setElementData(element.$element, COMMAND_MOVE_UP);
                    element = renderer.createRect(offset1, -size, size2, size * 2).append(group);
                    setElementData(element.$element, COMMAND_MOVE_RIGHT);
                    element = renderer.createRect(-size, offset1, size * 2, size2).append(group);
                    setElementData(element.$element, COMMAND_MOVE_DOWN);
                    element = renderer.createRect(-offset2, -size, size2, size * 2).append(group);
                    setElementData(element.$element, COMMAND_MOVE_LEFT);
                    element = renderer.createCircle(0, options.incButtonOffset, options.smallCircleSize / 2).append(group);
                    setElementData(element.$element, COMMAND_ZOOM_IN);
                    element = renderer.createCircle(0, options.decButtonOffset, options.smallCircleSize / 2).append(group);
                    setElementData(element.$element, COMMAND_ZOOM_OUT);
                    element = this._zoomDragCover = renderer.createRect(-options.sliderLength / 2, options.sliderLineEndOffset - options.sliderWidth / 2, options.sliderLength, options.sliderWidth).append(group);
                    setElementData(element.$element, COMMAND_ZOOM_DRAG)
                },
                dispose: function() {
                    var self = this;
                    delete self._container;
                    self._dispose();
                    self._root.clear();
                    delete self._root;
                    delete self._buttonsGroup;
                    delete self._zoomDrag;
                    delete self._zoomDragCover;
                    return self
                },
                setZoom: function(zoom) {
                    this._adjustZoom(_ln(zoom) / _LN2);
                    return this
                },
                setOptions: function(options) {
                    options = options || {};
                    this._enabled = options.enabled !== undefined ? !!options.enabled : true;
                    this._buttonsGroup.applySettings(options.shape);
                    return this
                },
                clean: function() {
                    this._enabled && this._root.detach();
                    return this
                },
                render: function() {
                    this._enabled && this._root.append(this._container);
                    return this
                },
                _adjustZoom: function(zoomFactor) {
                    var value = zoomFactor;
                    value <= 5 || (value = 5);
                    value >= 0 || (value = 0);
                    this._zoomFactor = value;
                    var offset = -value * this._zoomCoeff;
                    this._zoomDrag.applySettings({translateY: offset});
                    this._zoomDragCover.applySettings({translateY: offset})
                },
                _applyZoom: function() {
                    this._zoom(_pow(2, this._zoomFactor))
                },
                processStart: function(arg) {
                    var commandType = COMMAND_TO_TYPE_MAP[arg.data] || MoveScreenCommand;
                    this._command = new commandType(this, arg);
                    return this
                },
                processMove: function(arg) {
                    this._command.update(arg);
                    return this
                },
                processEnd: function(arg) {
                    this._command.finish(arg);
                    return this
                },
                processWheel: function(arg) {
                    this._adjustZoom(this._zoomFactor + arg.delta * 0.5);
                    this._applyZoom();
                    return this
                }
            });
        function disposeCommand(command) {
            delete command._owner;
            command.update = function(){};
            command.finish = function(){}
        }
        function MoveScreenCommand(owner, arg) {
            this._owner = owner;
            this._x = arg.x;
            this._y = arg.y
        }
        MoveScreenCommand.prototype.update = function(arg) {
            var self = this;
            self._owner._move(self._x - arg.x, self._y - arg.y);
            self._x = arg.x;
            self._y = arg.y
        };
        MoveScreenCommand.prototype.finish = function() {
            disposeCommand(this)
        };
        function ResetCommand(owner, arg) {
            this._owner = owner;
            this._command = arg.data
        }
        ResetCommand.prototype.update = function(arg) {
            arg.data !== this._command && disposeCommand(this)
        };
        ResetCommand.prototype.finish = function() {
            this._owner._reset();
            this._owner._adjustZoom(0);
            disposeCommand(this)
        };
        function MoveCommand(owner, arg) {
            this._command = arg.data;
            var timeout = null,
                interval = 100,
                dx = 0,
                dy = 0;
            switch (this._command) {
                case COMMAND_MOVE_UP:
                    dy = -10;
                    break;
                case COMMAND_MOVE_RIGHT:
                    dx = 10;
                    break;
                case COMMAND_MOVE_DOWN:
                    dy = 10;
                    break;
                case COMMAND_MOVE_LEFT:
                    dx = -10;
                    break
            }
            function callback() {
                owner._move(dx, dy);
                timeout = _setTimeout(callback, interval)
            }
            this._stop = function() {
                _clearTimeout(timeout);
                this._stop = owner = callback = null;
                return this
            };
            arg = null;
            callback()
        }
        MoveCommand.prototype.update = function(arg) {
            this._command !== arg.data && this.finish()
        };
        MoveCommand.prototype.finish = function() {
            disposeCommand(this._stop())
        };
        function ZoomCommand(owner, arg) {
            this._owner = owner;
            this._command = arg.data;
            var timeout = null,
                interval = 150,
                dzoom = this._command === COMMAND_ZOOM_IN ? 0.5 : -0.5;
            function callback() {
                owner._adjustZoom(owner._zoomFactor + dzoom);
                timeout = _setTimeout(callback, interval)
            }
            this._stop = function() {
                _clearTimeout(timeout);
                this._stop = owner = callback = null;
                return this
            };
            arg = null;
            callback()
        }
        ZoomCommand.prototype.update = function(arg) {
            this._command !== arg.data && this.finish()
        };
        ZoomCommand.prototype.finish = function() {
            this._owner._applyZoom();
            disposeCommand(this._stop())
        };
        function ZoomDragCommand(owner, arg) {
            this._owner = owner;
            this._pos = arg.y
        }
        ZoomDragCommand.prototype.update = function(arg) {
            this._owner._adjustZoom(this._owner._zoomFactor + (this._pos - arg.y) / this._owner._zoomCoeff);
            this._pos = arg.y
        };
        ZoomDragCommand.prototype.finish = function() {
            this._owner._applyZoom();
            disposeCommand(this)
        };
        DX.viz.map._tests.ControlBar = ControlBar;
        DX.viz.map.Map.include({_controlBarType: ControlBar});
        var Tooltip = DX.Class.inherit({
                ctor: function(parameters) {
                    var self = this;
                    self._container = parameters.container;
                    self._root = parameters.renderer.createGroup({'class': 'dxm-tooltip'});
                    self._renderer = parameters.renderer;
                    self._inner = new DX.viz.charts.Tooltip({
                        renderer: parameters.renderer,
                        arrowLength: 10,
                        paddingLeftRight: 12,
                        paddingTopBottom: 10
                    }, self._root);
                    self._inner.draw();
                    self._inner.text.applySettings({'class': 'dxm-tooltip-text'});
                    self._enabled = false
                },
                dispose: function() {
                    var self = this;
                    self._inner.dispose(),
                    delete self._inner;
                    delete self._container;
                    self._root.clear();
                    delete self._root;
                    return self
                },
                enabled: function() {
                    return this._enabled
                },
                setSize: function(width, height) {
                    this._inner.update({
                        canvasWidth: width,
                        canvasHeight: height
                    });
                    return this
                },
                setOptions: function(options) {
                    var self = this;
                    options = options || {};
                    self._enabled = !!options.enabled;
                    self._inner.update({color: options.color || null});
                    self._inner.cloud.applySettings(options.shape);
                    self._inner.text.applySettings(options.text);
                    self._customizeText = _isFunction(options.customizeText) ? options.customizeText : null;
                    return self
                },
                clean: function() {
                    this._root.detach();
                    this._inner.hide();
                    return this
                },
                render: function() {
                    this._root.append(this._container);
                    return this
                },
                check: function(target) {
                    if (this._enabled) {
                        var text = this._customizeText ? this._customizeText.call(target, target) : null;
                        return !!(this._text = text !== null && text !== undefined ? _String(text) : '')
                    }
                    return false
                },
                show: function() {
                    this._inner.show();
                    return this
                },
                hide: function() {
                    this._inner.hide();
                    return this
                },
                move: function(options) {
                    this._inner.move(options.x, options.y, 12, this._text);
                    return this
                }
            });
        DX.viz.map._tests.Tooltip = Tooltip;
        DX.viz.map.Map.include({_tooltipType: Tooltip});
        var Legend = DX.Class.inherit({
                ctor: function(parameters) {
                    var self = this;
                    self._container = parameters.container;
                    self._renderer = parameters.renderer;
                    self._themeManager = parameters.themeManager;
                    self._root = self._renderer.createGroup({'class': 'dxm-legend'});
                    self._background = self._renderer.createRect(0, 0, 0, 0, 0, {'class': 'dxm-legend-background'}).append(self._root);
                    self._itemsGroup = self._renderer.createGroup().append(self._root);
                    self._clip = self._renderer.createClipRect().append();
                    self._itemsGroup.applySettings({clipId: self._clip.id})
                },
                dispose: function() {
                    var self = this;
                    self._root.clear();
                    self._clip.dispose();
                    self._root = self._background = self._itemsGroup = self._clip = self._container = self._renderer = null;
                    return self
                },
                setSize: function(width, height) {
                    var self = this;
                    self._containerWidth = width;
                    self._containerHeight = height;
                    self._hasItems && self._adjustLocation();
                    return self
                },
                setOptions: function(options) {
                    options = options || {};
                    var self = this;
                    self._items = options.items && options.items.length > 0 ? options.items : [];
                    self._enabled = (options.enabled !== undefined ? !!options.enabled : true) && self._items.length > 0;
                    self._metrics = options.metrics;
                    self._backgroundSettings = options.background;
                    self._textSettings = options.text;
                    return self
                },
                _createItems: function() {
                    var self = this,
                        metrics = self._metrics,
                        renderer = self._renderer,
                        themeManager = self._themeManager,
                        textSettings = self._textSettings,
                        group = self._itemsGroup,
                        items = self._items,
                        i,
                        ii = items.length,
                        item,
                        texts = [],
                        bbox,
                        leftOffset = metrics.horizontalPadding,
                        topOffset = metrics.verticalPadding,
                        itemSize = metrics.itemSize,
                        itemSpacing = metrics.itemSpacing,
                        textIndent = metrics.textIndent,
                        actualItemSize,
                        position;
                    for (i = 0; i < ii; ++i)
                        texts.push(renderer.createText(items[i].text, 0, 0, textSettings).append(group));
                    for (i = 0; i < ii; ++i) {
                        bbox = texts[i].getBBox();
                        actualItemSize = _max(itemSize, bbox.height);
                        position = topOffset + actualItemSize / 2;
                        renderer.createRect(leftOffset, position - itemSize / 2, itemSize, itemSize, 0, themeManager.getLegendItemSettings(items[i])).append(group);
                        texts[i].applySettings({
                            x: leftOffset + itemSize + textIndent,
                            y: position - bbox.y - bbox.height / 2
                        });
                        topOffset += actualItemSize + itemSpacing
                    }
                    self._totalWidth = _min(self._metrics.maxWidth, group.getBBox().width + 2 * metrics.horizontalPadding);
                    self._totalHeight = _min(self._metrics.maxHeight, topOffset + metrics.verticalPadding - itemSpacing);
                    self._background.applySettings({
                        x: 0,
                        y: 0,
                        width: self._totalWidth,
                        height: self._totalHeight
                    });
                    self._clip.updateRectangle({
                        x: 0,
                        y: 0,
                        width: self._totalWidth,
                        height: self._totalHeight
                    });
                    self._adjustLocation();
                    self._hasItems = true
                },
                _adjustLocation: function() {
                    var self = this;
                    self._root.applySettings({
                        translateX: self._containerWidth - self._totalWidth - self._metrics.horizontalIndent,
                        translateY: self._containerHeight - self._totalHeight - self._metrics.verticalIndent
                    })
                },
                clean: function() {
                    var self = this;
                    if (self._enabled) {
                        self._root.detach();
                        self._itemsGroup.clear();
                        self._hasItems = null
                    }
                    return self
                },
                render: function() {
                    var self = this;
                    if (self._enabled) {
                        self._background.applySettings(self._backgroundSettings);
                        self._root.append(self._container);
                        self._createItems()
                    }
                    return self
                }
            });
        DX.viz.map._tests.Legend = Legend;
        DX.viz.map.Map.include({_legendType: Legend});
        function ElementProxy(map, info, settings) {
            var self = this;
            self._debug_map = map;
            self._debug_info = info;
            self.selected = function(state) {
                var current = !!info.selected;
                if (state !== undefined) {
                    !!state !== current && settings.setSelectionCallback.call(map, info, !current);
                    return this
                }
                return current
            };
            self.type = settings.type;
            var attributes = info.attributes;
            self.attribute = function(name) {
                return attributes[name]
            };
            var options = info.options;
            self.option = function(name, value) {
                return options[name]
            };
            self._dispose = function() {
                map = info = attributes = options = null;
                self._debug_map = self._debug_info = null
            }
        }
        DX.viz.map._tests.ElementProxy = ElementProxy;
        DX.ui.registerComponent('dxVectorMap', DX.viz.map.Map);
        DX.viz.map.sources = {}
    })(DevExpress, jQuery);
    DevExpress.MOD_VIZ_VECTORMAP = true
}
if (!DevExpress.MOD_VIZ_SPARKLINES) {
    if (!window.DevExpress)
        throw Error('Required module is not referenced: core');
    if (!DevExpress.MOD_VIZ_CORE)
        throw Error('Required module is not referenced: viz-core');
    /*! Module viz-sparklines, file baseSparkline.js */
    (function($, DX) {
        var charts = DX.viz.charts,
            TOOLTIP_MARGIN = 100,
            TOOLTIP_ARROW_MARGIN = 10,
            DEFAULT_EVENTS_DELAY = 200,
            TOUCH_EVENTS_DELAY = 1000,
            _math = Math,
            _extend = $.extend,
            _setTimeout = setTimeout,
            _clearTimeout = clearTimeout,
            _abs = _math.abs,
            _String = String,
            _Number = Number,
            _round = _math.round;
        DX.viz.sparklines = {};
        DX.viz.sparklines.BaseSparkline = DX.ui.Component.inherit({
            render: function() {
                this._refresh();
                return this
            },
            _rendererType: DX.viz.renderers.Renderer,
            _clean: function() {
                this._tooltipContainer.detach();
                this._cleanWidgetElements()
            },
            _optionChanged: function(optionName, value) {
                if (optionName === 'size' && this._allOptions) {
                    this._clean();
                    this._canvas = this._calculateCanvas();
                    this._renderer.resize(this._canvas.width, this._canvas.height);
                    if (!this._isContainerVisible())
                        return;
                    this._allOptions.size = value;
                    this._redrawWidgetElements();
                    this._prepareTooltipContainer()
                }
                else {
                    this._invalidate();
                    this.callBase.apply(this, arguments)
                }
            },
            _init: function() {
                this._renderer = new this._rendererType({cssClass: this._widgetClass + ' ' + this._widgetClass + '-' + this._widgetType});
                this._renderer.recreateCanvas(1, 1);
                this._createHtmlElements();
                this._createTooltipGroups();
                this._initTooltipEvents();
                this._drawContainer()
            },
            _dispose: function() {
                this.callBase();
                this._disposeWidgetElements();
                this._disposeTooltipEvents();
                this._renderer.killContainer();
                this._tooltipRenderer.killContainer();
                delete this._renderer;
                delete this._tooltipRenderer;
                delete this._tooltipTrackerGroup;
                delete this._tooltipGroup;
                delete this._tooltipContainer
            },
            _render: function() {
                this._canvas = this._calculateCanvas();
                this._renderer.resize(this._canvas.width, this._canvas.height);
                if (!this._isContainerVisible())
                    return;
                this._prepareOptions();
                this._createWidgetElements();
                this._drawWidgetElements()
            },
            _isContainerVisible: function() {
                var _this = this,
                    canvas = _this._canvas,
                    enoughWidth = canvas.width - canvas.left - canvas.right > 0,
                    enoughHeight = canvas.height - canvas.top - canvas.bottom > 0;
                return canvas.height && canvas.width && enoughHeight && enoughWidth
            },
            _createWidgetElements: function() {
                this._createRange();
                this._createTranslator()
            },
            _prepareOptions: function(defaultOptions) {
                var _this = this,
                    core = DX.viz.core,
                    userOptions = _this.option() || {},
                    options,
                    defaultTheme,
                    theme;
                defaultTheme = core.findTheme('default');
                defaultTheme = defaultTheme[this._widgetType];
                options = _extend(true, {}, defaultOptions, userOptions);
                if (typeof options.theme === 'string') {
                    theme = core.findTheme(options.theme);
                    theme = theme[this._widgetType]
                }
                else
                    theme = options.theme;
                return _extend(true, {}, defaultTheme, theme, options)
            },
            _calculateCanvas: function() {
                var _this = this,
                    canvas = {},
                    sizeOptions = _this.option('size') || {},
                    marginOptions = _this.option('margin') || {},
                    defaultSize = _this._defaultSize,
                    container = _this._element(),
                    width = sizeOptions.width >= 0 ? _Number(sizeOptions.width) : container.width(),
                    height = sizeOptions.height >= 0 ? _Number(sizeOptions.height) : container.height();
                if (!width && _Number(sizeOptions.width) !== 0)
                    width = defaultSize.width;
                if (!height && _Number(sizeOptions.height) !== 0)
                    height = defaultSize.height;
                return {
                        width: width,
                        height: height,
                        top: _Number(marginOptions.top) || defaultSize.top,
                        bottom: _Number(marginOptions.bottom) || defaultSize.bottom,
                        left: _Number(marginOptions.left) || defaultSize.left,
                        right: _Number(marginOptions.right) || defaultSize.right
                    }
            },
            _createTooltipGroups: function() {
                var _this = this,
                    renderer,
                    root,
                    widgetClass = _this._widgetClass;
                _this._tooltipRenderer = renderer = new _this._rendererType({cssClass: widgetClass + ' ' + widgetClass + '-tooltip'});
                renderer.recreateCanvas(1, 1);
                _this._tooltipContainer = $('<div style="position: relative">');
                renderer.draw(_this._tooltipContainer[0]);
                root = renderer.getRoot();
                _this._tooltipGroup = renderer.createGroup({
                    'class': widgetClass + '-tooltip-group',
                    style: {'z-index': '1'}
                }).append(root);
                _this._tooltipTrackerGroup = renderer.createGroup({'class': widgetClass + '-tooltip-tracker-group'}).append(root);
                _this._tooltipTracker = _this._createTooltipTracker().append(_this._tooltipTrackerGroup);
                _this._tooltip = charts.factory.createTooltip({renderer: renderer}, _this._tooltipGroup)
            },
            _createTooltipTracker: function() {
                return this._tooltipRenderer.createRect(0, 0, 0, 0, 0, {
                        fill: 'grey',
                        opacity: 0
                    })
            },
            _initTooltipEvents: function() {
                var _this = this,
                    data = {
                        widget: _this,
                        container: _this._tooltipTracker
                    };
                _this._showTooltipCallback = function() {
                    _this._showTooltipTimeout = null;
                    if (!_this._tooltipShown) {
                        _this._tooltipShown = true;
                        _this._showTooltip()
                    }
                    _this._DEBUG_showCallback && _this._DEBUG_showCallback()
                };
                _this._hideTooltipCallback = function() {
                    _this._hideTooltipTimeout = null;
                    if (_this._tooltipShown) {
                        _this._tooltipShown = false;
                        _this._hideTooltip()
                    }
                    _this._DEBUG_hideCallback && _this._DEBUG_hideCallback()
                };
                _this._disposeCallbacks = function() {
                    _this = _this._showTooltipCallback = _this._hideTooltipCallback = _this._disposeCallbacks = null
                };
                _this._tooltipTracker.on(mouseEvents, data).on(touchEvents, data);
                _this._tooltipTracker.on(menuEvents)
            },
            _disposeTooltipEvents: function() {
                this._tooltipTracker.off();
                this._disposeCallbacks()
            },
            _drawContainer: function() {
                this._renderer.draw(this._element()[0])
            },
            _createTranslator: function() {
                this._translator = new DX.viz.core.Translator2D(this._range, this._canvas)
            },
            _prepareTooltipOptions: function() {
                var _this = this,
                    canvas = _this._canvas,
                    text = _this._getTooltipText(),
                    size = _this._getTooltipSize(true),
                    defaultOptions = {
                        canvasWidth: size.width,
                        canvasHeight: size.height,
                        paddingLeftRight: _this._allOptions.tooltip.paddingLeftRight,
                        paddingTopBottom: _this._allOptions.tooltip.paddingTopBottom,
                        arrowLength: _this._allOptions.tooltip.arrowLength,
                        cloudHorizontalPosition: _this._allOptions.tooltip.horizontalAlignment,
                        cloudVerticalPosition: _this._allOptions.tooltip.verticalAlignment
                    },
                    options = $.extend(defaultOptions, _this._allOptions.tooltip);
                _this._tooltipOptions = {
                    text: text,
                    size: size,
                    options: options
                }
            },
            _getTooltipText: function() {
                var _this = this,
                    customizeText = _this._allOptions.tooltip.customizeText,
                    customizeObject = _this._getTooltipData(),
                    generatedText,
                    text;
                if (typeof customizeText === 'function') {
                    text = customizeText.call(customizeObject, customizeObject);
                    if (text !== undefined && text !== null && text !== '')
                        generatedText = _String(text);
                    else
                        generatedText = null
                }
                else
                    generatedText = this._getDefaultTooltipText(customizeObject);
                return generatedText
            },
            _prepareTooltipContainer: function() {
                var _this = this,
                    canvas = _this._canvas,
                    width = canvas.width,
                    height = canvas.height,
                    renderer = _this._tooltipRenderer;
                _this._tooltipTracker.applySettings({
                    width: width,
                    height: height
                });
                renderer.resize(width, height);
                renderer.getRoot().applySettings({style: {
                        top: -height,
                        position: 'absolute',
                        left: 0
                    }});
                _this._tooltipContainer.appendTo(_this._element());
                _this._tooltipInitializated = false;
                _this._canShowTooltip = _this._allOptions.tooltip.enabled
            },
            _isTooltipVisible: function() {
                var _this = this,
                    tooltipEnabled = _this._allOptions.tooltip.enabled,
                    tooltipNotEmpty = _this._tooltipOptions.text !== null,
                    dataSourceNotEmpty;
                if (_this._widgetType === 'sparkline')
                    dataSourceNotEmpty = _this._dataSource.length !== 0;
                else
                    dataSourceNotEmpty = true;
                return tooltipEnabled && tooltipNotEmpty && dataSourceNotEmpty
            },
            _createTooltip: function() {
                var _this = this,
                    tooltip = _this._tooltip;
                _this._prepareTooltipOptions();
                if (_this._isTooltipVisible()) {
                    tooltip.update(_this._tooltipOptions.options);
                    tooltip.draw();
                    _this._updateTooltipSizeToWide();
                    _this._checkTooltipSize();
                    _this._updateTooltipSizeToNormal();
                    tooltip.cloud.applySettings({opacity: _this._allOptions.tooltip.opacity})
                }
                else
                    _this._canShowTooltip = false
            },
            _doShowTooltip: function(delay) {
                var _this = this;
                if (!_this._canShowTooltip)
                    return;
                ++_this._DEBUG_clearHideTooltipTimeout;
                _clearTimeout(_this._hideTooltipTimeout);
                _this._hideTooltipTimeout = null;
                _clearTimeout(_this._showTooltipTimeout);
                ++_this._DEBUG_showTooltipTimeoutSet;
                _this._showTooltipTimeout = _setTimeout(_this._showTooltipCallback, delay)
            },
            _doHideTooltip: function(delay) {
                var _this = this;
                if (!_this._canShowTooltip)
                    return;
                ++_this._DEBUG_clearShowTooltipTimeout;
                _clearTimeout(_this._showTooltipTimeout);
                _this._showTooltipTimeout = null;
                _clearTimeout(_this._hideTooltipTimeout);
                ++_this._DEBUG_hideTooltipTimeoutSet;
                _this._hideTooltipTimeout = _setTimeout(_this._hideTooltipCallback, delay)
            },
            _getNormalTooltipSize: function(wideDelta) {
                var size = {};
                size.width = this._canvas.width;
                size.left = 0;
                size.tooltipLeft = _round(size.width / 2);
                return size
            },
            _getWideTooltipSize: function(wideDelta) {
                var _this = this,
                    canvas = _this._canvas,
                    horizontalPos = _this._allOptions.tooltip.horizontalAlignment,
                    size = {};
                size.width = wideDelta + canvas.width;
                if (horizontalPos === 'right') {
                    size.left = 0;
                    size.tooltipLeft = _round(canvas.width / 2)
                }
                else if (horizontalPos === 'left') {
                    size.left = -wideDelta;
                    size.tooltipLeft = _round(canvas.width / 2) + wideDelta
                }
                else {
                    size.left = -_round(wideDelta / 2);
                    size.tooltipLeft = _round(size.width / 2)
                }
                return size
            },
            _getTooltipSize: function(isNormal, wideDelta) {
                var _this = this,
                    canvas = _this._canvas,
                    isVerticalPosTop = _this._allOptions.tooltip.verticalAlignment === 'top',
                    size = isNormal ? _this._getNormalTooltipSize(wideDelta) : _this._getWideTooltipSize(wideDelta);
                size.height = canvas.height + TOOLTIP_MARGIN;
                size.top = isVerticalPosTop ? -size.height : -canvas.height;
                size.trackerY = isVerticalPosTop ? TOOLTIP_MARGIN : 0;
                size.tooltipY = isVerticalPosTop ? _round(canvas.height / 2) + TOOLTIP_MARGIN - TOOLTIP_ARROW_MARGIN : _round(canvas.height / 2);
                return size
            },
            _checkTooltipSize: function() {
                var _this = this,
                    canvas = _this._canvas,
                    tooltipWidth = _this._tooltip.text.getBBox().width + 2 * _this._tooltipOptions.options.paddingLeftRight,
                    tooltipPlaceholderWidth,
                    horizontalPos = _this._allOptions.tooltip.horizontalAlignment,
                    getWide = _this._allOptions.tooltip.allowContainerResizing,
                    size;
                if (horizontalPos === 'left' || horizontalPos === 'right')
                    tooltipPlaceholderWidth = canvas.width / 2;
                else
                    tooltipPlaceholderWidth = canvas.width;
                if (tooltipWidth > tooltipPlaceholderWidth)
                    if (getWide) {
                        _this._tooltipOptions.size = size = _this._getTooltipSize(false, tooltipWidth - tooltipPlaceholderWidth);
                        _this._tooltipOptions.options.canvasWidth = size.width;
                        _this._tooltipOptions.options.canvasHeight = size.height;
                        _this._tooltip.update(_this._tooltipOptions.options);
                        _this._updateTooltipSizeToWide()
                    }
                    else
                        _this._canShowTooltip = false
            },
            _updateTooltipSizeToWide: function() {
                var _this = this,
                    size = _this._tooltipOptions.size,
                    renderer = _this._tooltipRenderer;
                renderer.resize(size.width, size.height);
                renderer.getRoot().applySettings({style: {
                        left: size.left,
                        top: size.top,
                        position: 'absolute'
                    }});
                _this._tooltipTracker.applySettings({
                    y: size.trackerY,
                    x: -size.left
                });
                _this._tooltip.move(size.tooltipLeft, size.tooltipY, 0, _this._tooltipOptions.text)
            },
            _updateTooltipSizeToNormal: function() {
                var _this = this,
                    renderer = _this._tooltipRenderer,
                    canvas = _this._canvas;
                renderer.resize(canvas.width, canvas.height);
                renderer.getRoot().applySettings({style: {
                        left: 0,
                        top: -canvas.height,
                        position: 'absolute'
                    }});
                _this._tooltipTracker.applySettings({
                    y: 0,
                    x: 0
                })
            },
            _showTooltip: function() {
                if (!this._tooltipInitializated) {
                    this._createTooltip();
                    this._tooltipInitializated = true;
                    if (!this._canShowTooltip)
                        return
                }
                this._updateTooltipSizeToWide();
                this._tooltip.show()
            },
            _hideTooltip: function() {
                this._updateTooltipSizeToNormal();
                this._tooltip.hide()
            }
        });
        var menuEvents = {
                'contextmenu.sparkline-tooltip': function(event) {
                    if (DX.ui.events.isTouchEvent(event) || DX.ui.events.isPointerEvent(event))
                        event.preventDefault()
                },
                'MSHoldVisual.sparkline-tooltip': function(event) {
                    event.preventDefault()
                }
            };
        var mouseEvents = {
                'mouseover.sparkline-tooltip': function(event) {
                    isPointerDownCalled = false;
                    var widget = event.data.widget;
                    widget._x = event.pageX;
                    widget._y = event.pageY;
                    widget._tooltipTracker.off(mouseMoveEvents).on(mouseMoveEvents, event.data);
                    widget._doShowTooltip(DEFAULT_EVENTS_DELAY)
                },
                'mouseout.sparkline-tooltip': function(event) {
                    if (isPointerDownCalled)
                        return;
                    var widget = event.data.widget;
                    widget._tooltipTracker.off(mouseMoveEvents);
                    widget._doHideTooltip(DEFAULT_EVENTS_DELAY)
                }
            };
        var mouseMoveEvents = {'mousemove.sparkline-tooltip': function(event) {
                    var widget = event.data.widget;
                    if (widget._showTooltipTimeout && (_abs(widget._x - event.pageX) > 3 || _abs(widget._y - event.pageY) > 3)) {
                        widget._x = event.pageX;
                        widget._y = event.pageY;
                        widget._doShowTooltip(DEFAULT_EVENTS_DELAY)
                    }
                }};
        var active_touch_tooltip_widget = null,
            touchstartTooltipProcessing = function(event) {
                event.preventDefault();
                var widget = active_touch_tooltip_widget;
                if (widget && widget !== event.data.widget)
                    widget._doHideTooltip(DEFAULT_EVENTS_DELAY);
                widget = active_touch_tooltip_widget = event.data.widget;
                widget._doShowTooltip(TOUCH_EVENTS_DELAY);
                widget._touch = true
            },
            touchstartDocumentProcessing = function() {
                var widget = active_touch_tooltip_widget;
                if (widget) {
                    if (!widget._touch) {
                        widget._doHideTooltip(DEFAULT_EVENTS_DELAY);
                        active_touch_tooltip_widget = null
                    }
                    widget._touch = null
                }
            },
            touchendDocumentProcessing = function() {
                var widget = active_touch_tooltip_widget;
                if (widget)
                    if (widget._showTooltipTimeout) {
                        widget._doHideTooltip(DEFAULT_EVENTS_DELAY);
                        active_touch_tooltip_widget = null
                    }
            },
            isPointerDownCalled = false;
        var touchEvents = {
                'pointerdown.sparkline-tooltip': function(event) {
                    touchstartTooltipProcessing(event)
                },
                'touchstart.sparkline-tooltip': function(event) {
                    touchstartTooltipProcessing(event)
                }
            };
        $(document).on({
            'pointerdown.sparkline-tooltip': function() {
                isPointerDownCalled = true;
                touchstartDocumentProcessing()
            },
            'touchstart.sparkline-tooltip': function() {
                touchstartDocumentProcessing()
            },
            'pointerup.sparkline-tooltip': function() {
                touchendDocumentProcessing()
            },
            'touchend.sparkline-tooltip': function() {
                touchendDocumentProcessing()
            }
        });
        DX.viz.sparklines.BaseSparkline._DEBUG_reset = function() {
            active_touch_tooltip_widget = null
        }
    })(jQuery, DevExpress);
    /*! Module viz-sparklines, file sparkline.js */
    (function($, DX) {
        var charts = DX.viz.charts,
            MIN_BAR_WIDTH = 1,
            MAX_BAR_WIDTH = 50,
            DEFAULT_BAR_INTERVAL = 4,
            DEFAULT_CANVAS_WIDTH = 250,
            DEFAULT_CANVAS_HEIGHT = 30,
            DEFAULT_HORIZONTAL_MARGIN = 5,
            DEFAULT_VERTICAL_MARGIN = 3,
            FIRST_LAST_POINTS_CLASS = 'dxsl-first-last-points',
            MIN_POINT_CLASS = 'dxsl-min-point',
            MAX_POINT_CLASS = 'dxsl-max-point',
            POSITIVE_POINTS_CLASS = 'dxsl-positive-points',
            NEGATIVE_POINTS_CLASS = 'dxsl-negative-points',
            DEFAULT_OPTIONS = {
                theme: 'default',
                dataSource: [],
                size: {},
                margin: {},
                type: 'line',
                argumentField: 'arg',
                valueField: 'val',
                winlossThreshold: 0,
                showFirstLast: true,
                showMinMax: false
            },
            ALLOWED_TYPES = {
                line: true,
                spline: true,
                stepline: true,
                area: true,
                steparea: true,
                splinearea: true,
                bar: true,
                winloss: true
            },
            _map = $.map,
            _extend = $.extend,
            _abs = Math.abs,
            _round = Math.round,
            _isFinite = isFinite,
            _Number = Number,
            _String = String,
            _formatHelper = DX.formatHelper;
        DX.viz.sparklines.Sparkline = DX.viz.sparklines.BaseSparkline.inherit({
            _widgetType: 'sparkline',
            _widgetClass: 'dxsl',
            _defaultSize: {
                width: DEFAULT_CANVAS_WIDTH,
                height: DEFAULT_CANVAS_HEIGHT,
                left: DEFAULT_HORIZONTAL_MARGIN,
                right: DEFAULT_HORIZONTAL_MARGIN,
                top: DEFAULT_VERTICAL_MARGIN,
                bottom: DEFAULT_VERTICAL_MARGIN
            },
            _redrawWidgetElements: function() {
                this._createTranslator();
                this._correctPoints();
                this._series.draw(this._translator);
                this._seriesGroup.append(this._renderer.getRoot())
            },
            _disposeWidgetElements: function() {
                delete this._seriesGroup;
                delete this._seriesLabelGroup
            },
            _cleanWidgetElements: function() {
                this._seriesGroup.detach();
                this._seriesLabelGroup.detach();
                this._seriesGroup.clear();
                this._seriesLabelGroup.clear()
            },
            _createWidgetElements: function() {
                this._createSeries();
                this.callBase()
            },
            _drawWidgetElements: function() {
                this._drawSeries()
            },
            _prepareOptions: function() {
                this._allOptions = this.callBase(DEFAULT_OPTIONS);
                this._allOptions.type = _String(this._allOptions.type).toLowerCase();
                if (!ALLOWED_TYPES[this._allOptions.type])
                    this._allOptions.type = 'line'
            },
            _createHtmlElements: function() {
                this._seriesGroup = this._renderer.createGroup({'class': 'dxsl-series'});
                this._seriesLabelGroup = this._renderer.createGroup({'class': 'dxsl-series-labels'})
            },
            _createSeries: function() {
                var _this = this,
                    renderer = _this._renderer,
                    dataValidator;
                _this._prepareDataSource();
                _this._prepareSeriesOptions();
                _this._series = charts.factory.createSeries(_this._seriesOptions.type, renderer, _this._seriesOptions);
                dataValidator = charts.factory.createDataValidator(_this._dataSource, [[_this._series]], null, {
                    checkTypeForAllData: false,
                    convertToAxisDataType: true,
                    sortingMethod: true
                });
                _this._dataSource = dataValidator.validate();
                _this._series.options.customizePoint = _this._getCustomizeFunction();
                _this._series.reinitData(_this._dataSource)
            },
            _parseNumericDataSource: function(data, argField, valField) {
                return _map(data, function(dataItem, index) {
                        var item = null,
                            isDataNumber;
                        if (dataItem !== undefined) {
                            item = {};
                            isDataNumber = _isFinite(dataItem);
                            item[argField] = isDataNumber ? _String(index) : dataItem[argField];
                            item[valField] = isDataNumber ? _Number(dataItem) : _Number(dataItem[valField]);
                            item = item[argField] !== undefined && item[valField] !== undefined ? item : null
                        }
                        return item
                    })
            },
            _parseWinlossDataSource: function(data, argField, valField) {
                var lowBarValue = -1,
                    zeroBarValue = 0,
                    highBarValue = 1,
                    delta = 0.0001,
                    target = this._allOptions.winlossThreshold;
                return _map(data, function(dataItem) {
                        var item = {};
                        item[argField] = dataItem[argField];
                        if (_abs(dataItem[valField] - target) < delta)
                            item[valField] = zeroBarValue;
                        else if (dataItem[valField] > target)
                            item[valField] = highBarValue;
                        else
                            item[valField] = lowBarValue;
                        return item
                    })
            },
            _prepareDataSource: function() {
                var _this = this,
                    options = _this._allOptions,
                    argField = options.argumentField,
                    valField = options.valueField,
                    dataSource = _this._parseNumericDataSource(options.dataSource || [], argField, valField);
                if (options.type === 'winloss') {
                    _this._winlossDataSource = dataSource;
                    _this._dataSource = _this._parseWinlossDataSource(dataSource, argField, valField)
                }
                else
                    _this._dataSource = dataSource
            },
            _prepareSeriesOptions: function() {
                var _this = this,
                    options = _this._allOptions,
                    defaultPointOptions = {
                        border: {},
                        hoverStyle: {border: {}},
                        selectionStyle: {border: {}}
                    },
                    customPointOptions = {
                        size: options.pointSize,
                        symbol: options.pointSymbol,
                        border: {
                            visible: true,
                            width: 2
                        },
                        color: options.pointColor
                    };
                _this._seriesOptions = {
                    argumentField: options.argumentField,
                    valueField: options.valueField,
                    color: options.lineColor,
                    width: options.lineWidth
                };
                _this._seriesOptions.type = options.type === 'winloss' ? 'bar' : options.type;
                if (options.type === 'winloss' || options.type === 'bar')
                    _this._seriesOptions.argumentAxisType = 'discrete';
                _this._seriesOptions.seriesGroup = _this._seriesGroup;
                _this._seriesOptions.seriesLabelsGroup = _this._seriesLabelGroup;
                _this._seriesOptions.point = _extend(defaultPointOptions, customPointOptions);
                _this._seriesOptions.point.visible = false;
                _this._seriesOptions.border = {
                    color: _this._seriesOptions.color,
                    width: _this._seriesOptions.width,
                    visible: true
                }
            },
            _createBarCustomizeFunction: function(pointIndexes) {
                var _this = this,
                    options = _this._allOptions,
                    winlossData = _this._winlossDataSource;
                return function() {
                        var index = this.index,
                            isWinloss = options.type === 'winloss',
                            target = isWinloss ? options.winlossThreshold : 0,
                            value = isWinloss ? winlossData[index][options.valueField] : this.value,
                            positiveColor = isWinloss ? options.winColor : options.barPositiveColor,
                            negativeColor = isWinloss ? options.lossColor : options.barNegativeColor,
                            color;
                        if (value >= target)
                            color = positiveColor;
                        else
                            color = negativeColor;
                        if (index === pointIndexes.first || index === pointIndexes.last)
                            color = options.firstLastColor;
                        if (index === pointIndexes.min)
                            color = options.minColor;
                        if (index === pointIndexes.max)
                            color = options.maxColor;
                        return {color: color}
                    }
            },
            _createLineCustomizeFunction: function(pointIndexes) {
                var _this = this,
                    options = _this._allOptions;
                return function() {
                        var color,
                            index = this.index;
                        if (index === pointIndexes.first || index === pointIndexes.last)
                            color = options.firstLastColor;
                        if (index === pointIndexes.min)
                            color = options.minColor;
                        if (index === pointIndexes.max)
                            color = options.maxColor;
                        return color ? {
                                visible: true,
                                border: {color: color}
                            } : {}
                    }
            },
            _getCustomizeFunction: function() {
                var _this = this,
                    options = _this._allOptions,
                    dataSource = _this._winlossDataSource || _this._dataSource,
                    drawnPointIndexes = _this._getExtremumPointsIndexes(dataSource),
                    customizeFunction;
                if (options.type === 'winloss' || options.type === 'bar')
                    customizeFunction = _this._createBarCustomizeFunction(drawnPointIndexes);
                else
                    customizeFunction = _this._createLineCustomizeFunction(drawnPointIndexes);
                return customizeFunction
            },
            _getExtremumPointsIndexes: function(data) {
                var _this = this,
                    options = _this._allOptions,
                    lastIndex = data.length - 1,
                    indexes = {};
                _this._minMaxIndexes = _this._findMinMax(data);
                if (options.showFirstLast) {
                    indexes.first = 0;
                    indexes.last = lastIndex
                }
                if (options.showMinMax) {
                    indexes.min = _this._minMaxIndexes.minIndex;
                    indexes.max = _this._minMaxIndexes.maxIndex
                }
                return indexes
            },
            _findMinMax: function(data) {
                var _this = this,
                    valField = _this._allOptions.valueField,
                    firstItem = data[0] || {},
                    firstValue = firstItem[valField] || 0,
                    min = firstValue,
                    max = firstValue,
                    minIndex = 0,
                    maxIndex = 0,
                    dataLength = data.length,
                    value,
                    i;
                for (i = 1; i < dataLength; i++) {
                    value = data[i][valField];
                    if (value < min) {
                        min = value;
                        minIndex = i
                    }
                    if (value > max) {
                        max = value;
                        maxIndex = i
                    }
                }
                return {
                        minIndex: minIndex,
                        maxIndex: maxIndex
                    }
            },
            _createRange: function() {
                var _this = this,
                    series = _this._series,
                    isBarType = series.type === 'bar',
                    DEFAULT_VALUE_RANGE_MARGIN = 0.15,
                    DEFAULT_ARGUMENT_RANGE_MARGIN = isBarType ? 0.1 : 0,
                    rangeData = {
                        stickX: !isBarType && series.points.length > 1,
                        minValueMarginY: DEFAULT_VALUE_RANGE_MARGIN,
                        maxValueMarginY: DEFAULT_VALUE_RANGE_MARGIN,
                        minValueMarginX: DEFAULT_ARGUMENT_RANGE_MARGIN,
                        maxValueMarginX: DEFAULT_ARGUMENT_RANGE_MARGIN
                    };
                _this._range = new charts.Range(rangeData);
                _this._range.getBoundRange(series.getRangeData());
                _this._range.applyValueMargins()
            },
            _getBarWidth: function(pointsCount) {
                var _this = this,
                    canvas = _this._canvas,
                    intervalWidth = pointsCount * DEFAULT_BAR_INTERVAL,
                    rangeWidth = canvas.width - canvas.left - canvas.right - intervalWidth,
                    width = _round(rangeWidth / pointsCount);
                if (width < MIN_BAR_WIDTH)
                    width = MIN_BAR_WIDTH;
                if (width > MAX_BAR_WIDTH)
                    width = MAX_BAR_WIDTH;
                return width
            },
            _preparePointsClasses: function() {
                var _this = this,
                    options = _this._allOptions,
                    isBar = options.type === 'bar',
                    isBarOrWinloss = isBar || options.type === 'winloss',
                    points = _this._series.getAllPoints(),
                    firstIndex = 0,
                    lastIndex = points.length - 1,
                    minIndex = _this._minMaxIndexes.minIndex,
                    maxIndex = _this._minMaxIndexes.maxIndex,
                    target = isBar ? 0 : options.winlossThreshold,
                    additionalClass = '';
                if (isBarOrWinloss) {
                    additionalClass = ' dxsl-bar-point';
                    $.each(points, function(index, point) {
                        var className;
                        if (point.value >= target)
                            className = POSITIVE_POINTS_CLASS;
                        else
                            className = NEGATIVE_POINTS_CLASS;
                        points[index].options.attributes['class'] = className
                    })
                }
                if (options.showFirstLast) {
                    points[firstIndex].options.attributes['class'] = FIRST_LAST_POINTS_CLASS + additionalClass;
                    points[lastIndex].options.attributes['class'] = FIRST_LAST_POINTS_CLASS + additionalClass
                }
                if (options.showMinMax) {
                    points[minIndex].options.attributes['class'] = MIN_POINT_CLASS + additionalClass;
                    points[maxIndex].options.attributes['class'] = MAX_POINT_CLASS + additionalClass
                }
            },
            _correctPoints: function() {
                var _this = this,
                    seriesType = _this._allOptions.type,
                    seriesPoints = _this._series.getPoints(),
                    pointsLength = seriesPoints.length,
                    barWidth,
                    i;
                if (seriesType === 'bar' || seriesType === 'winloss') {
                    barWidth = _this._getBarWidth(pointsLength);
                    for (i = 0; i < pointsLength; i++)
                        seriesPoints[i].correctCoordinates({
                            width: barWidth,
                            offset: 0
                        })
                }
            },
            _drawSeries: function() {
                var _this = this;
                if (_this._dataSource.length !== 0) {
                    _this._correctPoints();
                    _this._series._segmentPoints();
                    if (_this._series.styles.area)
                        _this._series.styles.area.opacity = _this._allOptions.areaOpacity;
                    _this._preparePointsClasses();
                    _this._series.createPatterns = function(){};
                    _this._series.draw(_this._translator);
                    _this._seriesGroup.append(_this._renderer.getRoot());
                    _this._prepareTooltipContainer()
                }
            },
            _getTooltipData: function() {
                var _this = this,
                    options = _this._allOptions,
                    format = options.tooltip.format,
                    precision = options.tooltip.precision,
                    dataSource = _this._winlossDataSource || _this._dataSource;
                if (dataSource.length === 0)
                    return {};
                var minMax = _this._minMaxIndexes,
                    valueField = options.valueField,
                    first = dataSource[0][valueField],
                    last = dataSource[dataSource.length - 1][valueField],
                    min = dataSource[minMax.minIndex][valueField],
                    max = dataSource[minMax.maxIndex][valueField],
                    formattedFirst = _formatHelper.format(first, format, precision),
                    formattedLast = _formatHelper.format(last, format, precision),
                    formattedMin = _formatHelper.format(min, format, precision),
                    formattedMax = _formatHelper.format(max, format, precision),
                    customizeObject = {
                        firstValue: formattedFirst,
                        lastValue: formattedLast,
                        minValue: formattedMin,
                        maxValue: formattedMax,
                        originalFirstValue: first,
                        originalLastValue: last,
                        originalMinValue: min,
                        originalMaxValue: max
                    };
                if (options.type === 'winloss') {
                    customizeObject.originalThresholdValue = options.winlossThreshold;
                    customizeObject.thresholdValue = _formatHelper.format(options.winlossThreshold, format, precision)
                }
                return customizeObject
            },
            _getDefaultTooltipText: function(customizeObject) {
                return 'Start: ' + customizeObject.firstValue + '<br/>End: ' + customizeObject.lastValue + '<br/>Min: ' + customizeObject.minValue + '<br/>Max: ' + customizeObject.maxValue
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-sparklines, file bullet.js */
    (function($, DX) {
        var charts = DX.viz.charts,
            TARGET_MIN_Y = 0.02,
            TARGET_MAX_Y = 0.98,
            BAR_VALUE_MIN_Y = 0.1,
            BAR_VALUE_MAX_Y = 0.9,
            DEFAULT_CANVAS_WIDTH = 300,
            DEFAULT_CANVAS_HEIGHT = 30,
            DEFAULT_HORIZONTAL_MARGIN = 1,
            DEFAULT_VERTICAL_MARGIN = 2,
            DEFAULT_OPTIONS = {
                theme: 'default',
                size: {},
                margin: {}
            },
            _formatHelper = DX.formatHelper,
            _String = String,
            _Number = Number,
            _isFinite = isFinite;
        DX.viz.sparklines.Bullet = DX.viz.sparklines.BaseSparkline.inherit({
            _widgetType: 'bullet',
            _widgetClass: 'dxb',
            _defaultSize: {
                width: DEFAULT_CANVAS_WIDTH,
                height: DEFAULT_CANVAS_HEIGHT,
                left: DEFAULT_HORIZONTAL_MARGIN,
                right: DEFAULT_HORIZONTAL_MARGIN,
                top: DEFAULT_VERTICAL_MARGIN,
                bottom: DEFAULT_VERTICAL_MARGIN
            },
            _disposeWidgetElements: function() {
                delete this._zeroLevelPath;
                delete this._targetPath;
                delete this._barValuePath
            },
            _redrawWidgetElements: function() {
                this._createTranslator();
                this._drawBarValue();
                this._drawTarget();
                this._drawZeroLevel()
            },
            _cleanWidgetElements: function() {
                this._zeroLevelPath.detach();
                this._targetPath.detach();
                this._barValuePath.detach()
            },
            _drawWidgetElements: function() {
                this._drawBullet()
            },
            _createHtmlElements: function() {
                var renderer = this._renderer;
                this._zeroLevelPath = renderer.createPath(undefined, {'class': 'dxb-zero-level'});
                this._targetPath = renderer.createPath(undefined, {'class': 'dxb-target'});
                this._barValuePath = renderer.createPath(undefined, {'class': 'dxb-bar-value'})
            },
            _prepareOptions: function() {
                var _this = this,
                    options,
                    startScaleValue,
                    endScaleValue,
                    level,
                    value,
                    target;
                _this._allOptions = options = _this.callBase(DEFAULT_OPTIONS);
                if (_this._allOptions.value === undefined)
                    _this._allOptions.value = 0;
                if (_this._allOptions.target === undefined)
                    _this._allOptions.target = 0;
                options.value = value = _Number(options.value);
                options.target = target = _Number(options.target);
                if (_this._allOptions.startScaleValue === undefined) {
                    _this._allOptions.startScaleValue = target < value ? target : value;
                    _this._allOptions.startScaleValue = _this._allOptions.startScaleValue < 0 ? _this._allOptions.startScaleValue : 0
                }
                if (_this._allOptions.endScaleValue === undefined)
                    _this._allOptions.endScaleValue = target > value ? target : value;
                options.startScaleValue = startScaleValue = _Number(options.startScaleValue);
                options.endScaleValue = endScaleValue = _Number(options.endScaleValue);
                if (endScaleValue < startScaleValue) {
                    level = endScaleValue;
                    _this._allOptions.endScaleValue = startScaleValue;
                    _this._allOptions.startScaleValue = level;
                    _this._allOptions.inverted = true
                }
            },
            _createRange: function() {
                var _this = this,
                    options = _this._allOptions;
                _this._range = {
                    invertX: options.inverted,
                    minX: options.startScaleValue,
                    maxX: options.endScaleValue,
                    minY: 0,
                    maxY: 1
                }
            },
            _drawBullet: function() {
                var _this = this,
                    options = _this._allOptions,
                    isValidBounds = options.startScaleValue !== options.endScaleValue,
                    isValidMin = _isFinite(options.startScaleValue),
                    isValidMax = _isFinite(options.endScaleValue),
                    isValidValue = _isFinite(options.value),
                    isValidTarget = _isFinite(options.target);
                if (isValidBounds && isValidMax && isValidMin && isValidTarget && isValidValue) {
                    this._drawBarValue();
                    this._drawTarget();
                    this._drawZeroLevel();
                    this._prepareTooltipContainer()
                }
            },
            _getTargetParams: function() {
                var _this = this,
                    options = _this._allOptions,
                    translator = _this._translator,
                    minY = translator.translateY(TARGET_MIN_Y),
                    maxY = translator.translateY(TARGET_MAX_Y),
                    x = translator.translateX(options.target),
                    points = [{
                            x: x,
                            y: minY
                        }, {
                            x: x,
                            y: maxY
                        }];
                return {
                        points: points,
                        stroke: options.targetColor,
                        strokeWidth: options.targetWidth
                    }
            },
            _getBarValueParams: function() {
                var _this = this,
                    options = _this._allOptions,
                    translator = _this._translator,
                    startLevel = options.startScaleValue,
                    endLevel = options.endScaleValue,
                    value = options.value,
                    y2 = translator.translateY(BAR_VALUE_MIN_Y),
                    y1 = translator.translateY(BAR_VALUE_MAX_Y),
                    x1,
                    x2;
                if (value > 0) {
                    x1 = startLevel <= 0 ? 0 : startLevel;
                    x2 = value >= endLevel ? endLevel : value
                }
                else {
                    x1 = endLevel >= 0 ? 0 : endLevel;
                    x2 = value >= startLevel ? value : startLevel
                }
                x1 = translator.translateX(x1);
                x2 = translator.translateX(x2);
                return {
                        points: [{
                                x: x1,
                                y: y1
                            }, {
                                x: x2,
                                y: y1
                            }, {
                                x: x2,
                                y: y2
                            }, {
                                x: x1,
                                y: y2
                            }],
                        fill: options.color
                    }
            },
            _getZeroLevelParams: function() {
                var _this = this,
                    options = _this._allOptions,
                    translator = _this._translator,
                    minY = translator.translateY(TARGET_MIN_Y),
                    maxY = translator.translateY(TARGET_MAX_Y),
                    x = translator.translateX(0);
                return {
                        points: [{
                                x: x,
                                y: minY
                            }, {
                                x: x,
                                y: maxY
                            }],
                        stroke: options.targetColor,
                        strokeWidth: 1
                    }
            },
            _drawZeroLevel: function() {
                var _this = this,
                    options = _this._allOptions,
                    params;
                if (0 > options.endScaleValue || 0 < options.startScaleValue || !options.showZeroLevel)
                    return;
                params = _this._getZeroLevelParams();
                _this._zeroLevelPath.applySettings(params);
                _this._zeroLevelPath.append(_this._renderer.getRoot())
            },
            _drawTarget: function() {
                var _this = this,
                    options = _this._allOptions,
                    target = options.target,
                    startLevel = options.startScaleValue,
                    endLevel = options.endScaleValue,
                    params;
                if (target > endLevel || target < startLevel || !options.showTarget)
                    return;
                params = _this._getTargetParams();
                _this._targetPath.applySettings(params);
                _this._targetPath.append(_this._renderer.getRoot())
            },
            _drawBarValue: function() {
                var _this = this,
                    params = _this._getBarValueParams();
                _this._barValuePath.applySettings(params);
                _this._barValuePath.append(_this._renderer.getRoot())
            },
            _getTooltipData: function() {
                var _this = this,
                    options = _this._allOptions,
                    format = options.tooltip.format,
                    precision = options.tooltip.precision,
                    valueField = options.valueField,
                    value = options.value,
                    target = options.target,
                    formattedValue = _formatHelper.format(value, format, precision),
                    formattedTarget = _formatHelper.format(target, format, precision);
                return {
                        originalValue: value,
                        originalTarget: target,
                        value: formattedValue,
                        target: formattedTarget
                    }
            },
            _getDefaultTooltipText: function(customizeObject) {
                return 'Actual Value: ' + customizeObject.value + '<br/>Target Value: ' + customizeObject.target
            }
        })
    })(jQuery, DevExpress);
    /*! Module viz-sparklines, file dxSparkline.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        ui.registerComponent("dxSparkline", viz.sparklines.Sparkline)
    })(jQuery, DevExpress);
    /*! Module viz-sparklines, file dxBullet.js */
    (function($, DX, undefined) {
        var ui = DX.ui,
            viz = DX.viz;
        ui.registerComponent("dxBullet", viz.sparklines.Bullet)
    })(jQuery, DevExpress);
    DevExpress.MOD_VIZ_SPARKLINES = true
}
